rustc: use partially resolved definitions to replace the T::A
hack.
This commit is contained in:
parent
5809f8ae74
commit
0f49254b31
@ -17,29 +17,47 @@
|
||||
use middle::def;
|
||||
use middle::ty::{self, Ty};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
pub const NO_REGIONS: uint = 1;
|
||||
pub const NO_TPS: uint = 2;
|
||||
|
||||
pub fn check_path_args(tcx: &ty::ctxt,
|
||||
path: &ast::Path,
|
||||
span: Span,
|
||||
segments: &[ast::PathSegment],
|
||||
flags: uint) {
|
||||
if (flags & NO_TPS) != 0 {
|
||||
if path.segments.iter().any(|s| s.parameters.has_types()) {
|
||||
span_err!(tcx.sess, path.span, E0109,
|
||||
if segments.iter().any(|s| s.parameters.has_types()) {
|
||||
span_err!(tcx.sess, span, E0109,
|
||||
"type parameters are not allowed on this type");
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & NO_REGIONS) != 0 {
|
||||
if path.segments.iter().any(|s| s.parameters.has_lifetimes()) {
|
||||
span_err!(tcx.sess, path.span, E0110,
|
||||
if segments.iter().any(|s| s.parameters.has_lifetimes()) {
|
||||
span_err!(tcx.sess, span, E0110,
|
||||
"lifetime parameters are not allowed on this type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
span: Span,
|
||||
segments: &[ast::PathSegment],
|
||||
nty: ast::PrimTy)
|
||||
-> Ty<'tcx> {
|
||||
check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS);
|
||||
match nty {
|
||||
ast::TyBool => tcx.types.bool,
|
||||
ast::TyChar => tcx.types.char,
|
||||
ast::TyInt(it) => ty::mk_mach_int(tcx, it),
|
||||
ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit),
|
||||
ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft),
|
||||
ast::TyStr => ty::mk_str(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
|
||||
-> Option<Ty<'tcx>> {
|
||||
if let ast::TyPath(ref path) = ast_ty.node {
|
||||
@ -51,15 +69,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
|
||||
Some(&d) => d
|
||||
};
|
||||
if let def::DefPrimTy(nty) = def {
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
Some(match nty {
|
||||
ast::TyBool => tcx.types.bool,
|
||||
ast::TyChar => tcx.types.char,
|
||||
ast::TyInt(it) => ty::mk_mach_int(tcx, it),
|
||||
ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit),
|
||||
ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft),
|
||||
ast::TyStr => ty::mk_str(tcx)
|
||||
})
|
||||
Some(prim_ty_to_ty(tcx, path.span, &path.segments[], nty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -444,10 +444,6 @@ impl tr for def::Def {
|
||||
def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
|
||||
def::DefAssociatedTy(trait_did, did) =>
|
||||
def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
|
||||
def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) =>
|
||||
def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident),
|
||||
def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) =>
|
||||
def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident),
|
||||
def::DefPrimTy(p) => def::DefPrimTy(p),
|
||||
def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
|
||||
def::DefUse(did) => def::DefUse(did.tr(dcx)),
|
||||
|
@ -33,11 +33,6 @@ pub enum Def {
|
||||
DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
|
||||
DefTy(ast::DefId, bool /* is_enum */),
|
||||
DefAssociatedTy(ast::DefId /* trait */, ast::DefId),
|
||||
// A partially resolved path to an associated type `T::U` where `T` is a concrete
|
||||
// type (indicated by the DefId) which implements a trait which has an associated
|
||||
// type `U` (indicated by the Ident).
|
||||
// FIXME(#20301) -- should use Name
|
||||
DefAssociatedPath(TyParamProvenance, ast::Ident),
|
||||
DefTrait(ast::DefId),
|
||||
DefPrimTy(ast::PrimTy),
|
||||
DefTyParam(ParamSpace, u32, ast::DefId, ast::Name),
|
||||
@ -59,8 +54,24 @@ pub enum Def {
|
||||
DefMethod(ast::DefId /* method */, Option<ast::DefId> /* trait */, MethodProvenance),
|
||||
}
|
||||
|
||||
/// The result of resolving the prefix of a path to a type:
|
||||
///
|
||||
/// module::Type::AssocA::AssocB::AssocC::MethodOrAssocType
|
||||
/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~
|
||||
/// base_type extra_associated_types
|
||||
///
|
||||
/// <T as Trait>::AssocA::AssocB::AssocC::MethodOrAssocType
|
||||
/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~
|
||||
/// base_type extra_associated_types
|
||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct PartialDef {
|
||||
pub base_type: Def,
|
||||
pub extra_associated_types: u32,
|
||||
}
|
||||
|
||||
// Definition mapping
|
||||
pub type DefMap = RefCell<NodeMap<Def>>;
|
||||
pub type PartialDefMap = RefCell<NodeMap<PartialDef>>;
|
||||
// This is the replacement export map. It maps a module to all of the exports
|
||||
// within.
|
||||
pub type ExportMap = NodeMap<Vec<Export>>;
|
||||
@ -77,12 +88,6 @@ pub enum MethodProvenance {
|
||||
FromImpl(ast::DefId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum TyParamProvenance {
|
||||
FromSelf(ast::DefId),
|
||||
FromParam(ast::DefId),
|
||||
}
|
||||
|
||||
impl MethodProvenance {
|
||||
pub fn map<F>(self, f: F) -> MethodProvenance where
|
||||
F: FnOnce(ast::DefId) -> ast::DefId,
|
||||
@ -94,15 +99,6 @@ impl MethodProvenance {
|
||||
}
|
||||
}
|
||||
|
||||
impl TyParamProvenance {
|
||||
pub fn def_id(&self) -> ast::DefId {
|
||||
match *self {
|
||||
TyParamProvenance::FromSelf(ref did) => did.clone(),
|
||||
TyParamProvenance::FromParam(ref did) => did.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum TraitItemKind {
|
||||
NonstaticMethodTraitItemKind,
|
||||
@ -135,9 +131,7 @@ impl Def {
|
||||
DefForeignMod(id) | DefStatic(id, _) |
|
||||
DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
|
||||
DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
|
||||
DefMethod(id, _, _) | DefConst(id) |
|
||||
DefAssociatedPath(TyParamProvenance::FromSelf(id), _) |
|
||||
DefAssociatedPath(TyParamProvenance::FromParam(id), _) => {
|
||||
DefMethod(id, _, _) | DefConst(id) => {
|
||||
id
|
||||
}
|
||||
DefLocal(id) |
|
||||
|
@ -582,7 +582,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
|
||||
def::DefTyParam(..) | def::DefRegion(_) |
|
||||
def::DefLabel(_) | def::DefSelfTy(..) |
|
||||
def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
|
||||
def::DefAssociatedTy(..) => {
|
||||
Ok(Rc::new(cmt_ {
|
||||
id:id,
|
||||
span:span,
|
||||
|
@ -46,7 +46,7 @@ use metadata::csearch;
|
||||
use middle;
|
||||
use middle::check_const;
|
||||
use middle::const_eval;
|
||||
use middle::def::{self, DefMap, ExportMap};
|
||||
use middle::def::{self, DefMap, ExportMap, PartialDefMap};
|
||||
use middle::dependency_format;
|
||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
||||
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
|
||||
@ -682,6 +682,7 @@ pub struct ctxt<'tcx> {
|
||||
|
||||
pub sess: Session,
|
||||
pub def_map: DefMap,
|
||||
pub partial_def_map: PartialDefMap,
|
||||
|
||||
pub named_region_map: resolve_lifetime::NamedRegionMap,
|
||||
|
||||
@ -2423,7 +2424,8 @@ impl<'tcx> CommonTypes<'tcx> {
|
||||
|
||||
pub fn mk_ctxt<'tcx>(s: Session,
|
||||
arenas: &'tcx CtxtArenas<'tcx>,
|
||||
dm: DefMap,
|
||||
def_map: DefMap,
|
||||
partial_def_map: PartialDefMap,
|
||||
named_region_map: resolve_lifetime::NamedRegionMap,
|
||||
map: ast_map::Map<'tcx>,
|
||||
freevars: RefCell<FreevarMap>,
|
||||
@ -2445,7 +2447,8 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||
item_variance_map: RefCell::new(DefIdMap()),
|
||||
variance_computed: Cell::new(false),
|
||||
sess: s,
|
||||
def_map: dm,
|
||||
def_map: def_map,
|
||||
partial_def_map: partial_def_map,
|
||||
region_maps: region_maps,
|
||||
node_types: RefCell::new(FnvHashMap()),
|
||||
item_substs: RefCell::new(NodeMap()),
|
||||
|
@ -567,6 +567,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
||||
|
||||
let resolve::CrateMap {
|
||||
def_map,
|
||||
partial_def_map,
|
||||
freevars,
|
||||
export_map,
|
||||
trait_map,
|
||||
@ -607,6 +608,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
|
||||
let ty_cx = ty::mk_ctxt(sess,
|
||||
arenas,
|
||||
def_map,
|
||||
partial_def_map,
|
||||
named_region_map,
|
||||
ast_map,
|
||||
freevars,
|
||||
|
@ -940,7 +940,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
|
||||
is_public,
|
||||
DUMMY_SP)
|
||||
}
|
||||
DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
|
||||
DefTy(..) | DefAssociatedTy(..) => {
|
||||
debug!("(building reduced graph for external \
|
||||
crate) building type {}", final_ident);
|
||||
|
||||
|
@ -935,6 +935,7 @@ struct Resolver<'a, 'tcx:'a> {
|
||||
primitive_type_table: PrimitiveTypeTable,
|
||||
|
||||
def_map: DefMap,
|
||||
partial_def_map: PartialDefMap,
|
||||
freevars: RefCell<FreevarMap>,
|
||||
freevars_seen: RefCell<NodeMap<NodeSet>>,
|
||||
export_map: ExportMap,
|
||||
@ -1008,6 +1009,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
primitive_type_table: PrimitiveTypeTable::new(),
|
||||
|
||||
def_map: RefCell::new(NodeMap()),
|
||||
partial_def_map: RefCell::new(NodeMap()),
|
||||
freevars: RefCell::new(NodeMap()),
|
||||
freevars_seen: RefCell::new(NodeMap()),
|
||||
export_map: NodeMap(),
|
||||
@ -2988,13 +2990,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
id: NodeId,
|
||||
trait_path: &Path,
|
||||
path_depth: usize)
|
||||
-> Result<(Def, LastPrivate), ()> {
|
||||
-> Result<(Def, LastPrivate, usize), ()> {
|
||||
match self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
|
||||
Some(def @ (DefTrait(_), _)) => {
|
||||
Some(def @ (DefTrait(_), _, _)) => {
|
||||
debug!("(resolving trait) found trait def: {:?}", def);
|
||||
Ok(def)
|
||||
}
|
||||
Some((def, _)) => {
|
||||
Some((def, _, _)) => {
|
||||
self.resolve_error(trait_path.span,
|
||||
&format!("`{}` is not a trait",
|
||||
self.path_names_to_string(trait_path, path_depth)));
|
||||
@ -3025,8 +3027,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
&ast::WherePredicate::RegionPredicate(_) => {}
|
||||
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
|
||||
match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) {
|
||||
Some((def @ DefTyParam(..), last_private)) => {
|
||||
self.record_def(eq_pred.id, (def, last_private));
|
||||
Some(def @ (DefTyParam(..), _, _)) => {
|
||||
self.record_def(eq_pred.id, def);
|
||||
}
|
||||
_ => {
|
||||
self.resolve_error(eq_pred.path.span,
|
||||
@ -3121,30 +3123,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Check that the current type is indeed a type, if we have an anonymous impl
|
||||
if opt_trait_reference.is_none() {
|
||||
match self_type.node {
|
||||
// TyPath is the only thing that we handled in `build_reduced_graph_for_item`,
|
||||
// where we created a module with the name of the type in order to implement
|
||||
// an anonymous trait. In the case that the path does not resolve to an actual
|
||||
// type, the result will be that the type name resolves to a module but not
|
||||
// a type (shadowing any imported modules or types with this name), leading
|
||||
// to weird user-visible bugs. So we ward this off here. See #15060.
|
||||
TyPath(ref path) => {
|
||||
match self.def_map.borrow().get(&self_type.id) {
|
||||
// FIXME: should we catch other options and give more precise errors?
|
||||
Some(&DefMod(_)) => {
|
||||
self.resolve_error(path.span, "inherent implementations are not \
|
||||
allowed for types not defined in \
|
||||
the current module");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_item(&self, name: Name, span: Span) {
|
||||
@ -3304,14 +3282,31 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
// on whether the path has multiple elements in it or not.
|
||||
|
||||
TyPath(ref path) | TyQPath(ast::QPath { ref path, .. }) => {
|
||||
if let TyQPath(_) = ty.node {
|
||||
let max_assoc_types = if let TyQPath(_) = ty.node {
|
||||
// Make sure the trait is valid.
|
||||
self.resolve_trait_reference(ty.id, path, 1);
|
||||
let _ = self.resolve_trait_reference(ty.id, path, 1);
|
||||
1
|
||||
} else {
|
||||
path.segments.len()
|
||||
};
|
||||
|
||||
let mut result = None;
|
||||
for depth in 0..max_assoc_types {
|
||||
self.with_no_errors(|this| {
|
||||
result = this.resolve_path(ty.id, path, depth, TypeNS, true);
|
||||
});
|
||||
if result.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some((DefMod(_), _, _)) = result {
|
||||
// A module is not a valid type.
|
||||
result = None;
|
||||
}
|
||||
|
||||
// This is a path in the type namespace. Walk through scopes
|
||||
// looking for it.
|
||||
match self.resolve_path(ty.id, path, 0, TypeNS, true) {
|
||||
match result {
|
||||
Some(def) => {
|
||||
// Write the result into the def map.
|
||||
debug!("(resolving type) writing resolution for `{}` \
|
||||
@ -3321,6 +3316,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.record_def(ty.id, def);
|
||||
}
|
||||
None => {
|
||||
// Keep reporting some errors even if they're ignored above.
|
||||
self.resolve_path(ty.id, path, 0, TypeNS, true);
|
||||
|
||||
let kind = match ty.node {
|
||||
TyQPath(_) => "associated type",
|
||||
_ => "type name"
|
||||
@ -3371,7 +3369,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
pattern,
|
||||
binding_mode,
|
||||
"an enum variant");
|
||||
self.record_def(pattern.id, (def, lp));
|
||||
self.record_def(pattern.id, (def, lp, 0));
|
||||
}
|
||||
FoundStructOrEnumVariant(..) => {
|
||||
self.resolve_error(
|
||||
@ -3390,7 +3388,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
pattern,
|
||||
binding_mode,
|
||||
"a constant");
|
||||
self.record_def(pattern.id, (def, lp));
|
||||
self.record_def(pattern.id, (def, lp, 0));
|
||||
}
|
||||
FoundConst(..) => {
|
||||
self.resolve_error(pattern.span,
|
||||
@ -3407,7 +3405,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
// will be able to distinguish variants from
|
||||
// locals in patterns.
|
||||
|
||||
self.record_def(pattern.id, (def, LastMod(AllPublic)));
|
||||
self.record_def(pattern.id, (def, LastMod(AllPublic), 0));
|
||||
|
||||
// Add the binding to the local ribs, if it
|
||||
// doesn't already exist in the bindings list. (We
|
||||
@ -3451,12 +3449,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
PatEnum(ref path, _) => {
|
||||
// This must be an enum variant, struct or const.
|
||||
match self.resolve_path(pat_id, path, 0, ValueNS, false) {
|
||||
Some(def @ (DefVariant(..), _)) |
|
||||
Some(def @ (DefStruct(..), _)) |
|
||||
Some(def @ (DefConst(..), _)) => {
|
||||
Some(def @ (DefVariant(..), _, _)) |
|
||||
Some(def @ (DefStruct(..), _, _)) |
|
||||
Some(def @ (DefConst(..), _, _)) => {
|
||||
self.record_def(pattern.id, def);
|
||||
}
|
||||
Some((DefStatic(..), _)) => {
|
||||
Some((DefStatic(..), _, _)) => {
|
||||
self.resolve_error(path.span,
|
||||
"static variables cannot be \
|
||||
referenced in a pattern, \
|
||||
@ -3573,40 +3571,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
path: &Path,
|
||||
path_depth: usize,
|
||||
namespace: Namespace,
|
||||
check_ribs: bool) -> Option<(Def, LastPrivate)> {
|
||||
check_ribs: bool) -> Option<(Def, LastPrivate, usize)> {
|
||||
let span = path.span;
|
||||
let segments = &path.segments[..path.segments.len()-path_depth];
|
||||
|
||||
// A special case for sugared associated type paths `T::A` where `T` is
|
||||
// a type parameter and `A` is an associated type on some bound of `T`.
|
||||
if namespace == TypeNS && segments.len() == 2 {
|
||||
match self.resolve_identifier(segments[0].identifier,
|
||||
TypeNS,
|
||||
true,
|
||||
span) {
|
||||
Some((def, last_private)) => {
|
||||
match def {
|
||||
DefTyParam(_, _, did, _) => {
|
||||
let def = DefAssociatedPath(TyParamProvenance::FromParam(did),
|
||||
segments.last()
|
||||
.unwrap().identifier);
|
||||
return Some((def, last_private));
|
||||
}
|
||||
DefSelfTy(nid) => {
|
||||
let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)),
|
||||
segments.last()
|
||||
.unwrap().identifier);
|
||||
return Some((def, last_private));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if path.global {
|
||||
return self.resolve_crate_relative_path(span, segments, namespace);
|
||||
let def = self.resolve_crate_relative_path(span, segments, namespace);
|
||||
return def.map(|(def, lp)| (def, lp, path_depth));
|
||||
}
|
||||
|
||||
// Try to find a path to an item in a module.
|
||||
@ -3628,10 +3599,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
_ => ()
|
||||
}
|
||||
|
||||
return def;
|
||||
def.map(|(def, lp)| (def, lp, path_depth))
|
||||
} else {
|
||||
unqualified_def.map(|(def, lp)| (def, lp, path_depth))
|
||||
}
|
||||
|
||||
unqualified_def
|
||||
}
|
||||
|
||||
// resolve a single identifier (used as a varref)
|
||||
@ -4105,14 +4076,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
ExprPath(ref path) | ExprQPath(ast::QPath { ref path, .. }) => {
|
||||
if let ExprQPath(_) = expr.node {
|
||||
// Make sure the trait is valid.
|
||||
self.resolve_trait_reference(expr.id, path, 1);
|
||||
let _ = self.resolve_trait_reference(expr.id, path, 1);
|
||||
}
|
||||
|
||||
// This is a local path in the value namespace. Walk through
|
||||
// scopes looking for it.
|
||||
match self.resolve_path(expr.id, path, 0, ValueNS, true) {
|
||||
// Check if struct variant
|
||||
Some((DefVariant(_, _, true), _)) => {
|
||||
Some((DefVariant(_, _, true), _, _)) => {
|
||||
let path_name = self.path_names_to_string(path, 0);
|
||||
self.resolve_error(expr.span,
|
||||
&format!("`{}` is a struct variant name, but \
|
||||
@ -4140,7 +4111,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
let path_name = self.path_names_to_string(path, 0);
|
||||
match self.with_no_errors(|this|
|
||||
this.resolve_path(expr.id, path, 0, TypeNS, false)) {
|
||||
Some((DefTy(struct_id, _), _))
|
||||
Some((DefTy(struct_id, _), _, 0))
|
||||
if self.structs.contains_key(&struct_id) => {
|
||||
self.resolve_error(expr.span,
|
||||
&format!("`{}` is a structure name, but \
|
||||
@ -4252,7 +4223,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
Some(DlDef(def @ DefLabel(_))) => {
|
||||
// Since this def is a label, it is never read.
|
||||
self.record_def(expr.id, (def, LastMod(AllPublic)))
|
||||
self.record_def(expr.id, (def, LastMod(AllPublic), 0))
|
||||
}
|
||||
Some(_) => {
|
||||
self.session.span_bug(expr.span,
|
||||
@ -4372,18 +4343,31 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
fn record_def(&mut self,
|
||||
node_id: NodeId,
|
||||
(def, lp): (Def, LastPrivate)) {
|
||||
(def, lp, depth): (Def, LastPrivate, usize)) {
|
||||
debug!("(recording def) recording {:?} for {}, last private {:?}",
|
||||
def, node_id, lp);
|
||||
assert!(match lp {LastImport{..} => false, _ => true},
|
||||
"Import should only be used for `use` directives");
|
||||
self.last_private.insert(node_id, lp);
|
||||
|
||||
if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) {
|
||||
let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
|
||||
self.session.span_bug(span, &format!("path resolved multiple times \
|
||||
({:?} before, {:?} now)",
|
||||
prev_def, def));
|
||||
if depth == 0 {
|
||||
if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) {
|
||||
let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
|
||||
self.session.span_bug(span, &format!("path resolved multiple times \
|
||||
({:?} before, {:?} now)",
|
||||
prev_def, def));
|
||||
}
|
||||
} else {
|
||||
let def = PartialDef {
|
||||
base_type: def,
|
||||
extra_associated_types: (depth - 1) as u32
|
||||
};
|
||||
if let Some(prev_def) = self.partial_def_map.borrow_mut().insert(node_id, def) {
|
||||
let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
|
||||
self.session.span_bug(span, &format!("path resolved multiple times \
|
||||
({:?} before, {:?} now)",
|
||||
prev_def, def));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4474,6 +4458,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
|
||||
pub struct CrateMap {
|
||||
pub def_map: DefMap,
|
||||
pub partial_def_map: PartialDefMap,
|
||||
pub freevars: RefCell<FreevarMap>,
|
||||
pub export_map: ExportMap,
|
||||
pub trait_map: TraitMap,
|
||||
@ -4513,6 +4498,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
|
||||
|
||||
CrateMap {
|
||||
def_map: resolver.def_map,
|
||||
partial_def_map: resolver.partial_def_map,
|
||||
freevars: resolver.freevars,
|
||||
export_map: resolver.export_map,
|
||||
trait_map: resolver.trait_map,
|
||||
|
@ -238,7 +238,6 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
|
||||
def::DefStruct(_) => Some(recorder::StructRef),
|
||||
def::DefTy(..) |
|
||||
def::DefAssociatedTy(..) |
|
||||
def::DefAssociatedPath(..) |
|
||||
def::DefTrait(_) => Some(recorder::TypeRef),
|
||||
def::DefStatic(_, _) |
|
||||
def::DefConst(_) |
|
||||
|
@ -210,7 +210,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
|
||||
def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
|
||||
def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
|
||||
def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) |
|
||||
def::DefTyParam(..) | def::DefSelfTy(..) | def::DefAssociatedPath(..) => {
|
||||
def::DefTyParam(..) | def::DefSelfTy(..) => {
|
||||
bcx.tcx().sess.span_bug(
|
||||
ref_expr.span,
|
||||
&format!("cannot translate def {:?} \
|
||||
|
@ -48,7 +48,7 @@
|
||||
//! case but `&a` in the second. Basically, defaults that appear inside
|
||||
//! an rptr (`&r.T`) use the region `r` that appears in the rptr.
|
||||
|
||||
use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS};
|
||||
use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS};
|
||||
use middle::const_eval;
|
||||
use middle::def;
|
||||
use middle::resolve_lifetime as rl;
|
||||
@ -57,13 +57,13 @@ use middle::traits;
|
||||
use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
|
||||
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
|
||||
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
|
||||
use TypeAndSubsts;
|
||||
use util::common::{ErrorReported, FN_OUTPUT_NAME};
|
||||
use util::nodemap::DefIdMap;
|
||||
use util::ppaux::{self, Repr, UserString};
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::iter::{repeat, AdditiveIterator};
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use syntax::{abi, ast, ast_util};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
@ -245,8 +245,9 @@ pub fn opt_ast_region_to_region<'tcx>(
|
||||
pub fn ast_path_substs_for_ty<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
path: &ast::Path)
|
||||
item_segment: &ast::PathSegment)
|
||||
-> Substs<'tcx>
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
@ -262,12 +263,12 @@ pub fn ast_path_substs_for_ty<'tcx>(
|
||||
assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
|
||||
assert!(decl_generics.types.all(|d| d.space != FnSpace));
|
||||
|
||||
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
|
||||
let (regions, types, assoc_bindings) = match item_segment.parameters {
|
||||
ast::AngleBracketedParameters(ref data) => {
|
||||
convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data)
|
||||
}
|
||||
ast::ParenthesizedParameters(ref data) => {
|
||||
span_err!(tcx.sess, path.span, E0214,
|
||||
span_err!(tcx.sess, span, E0214,
|
||||
"parenthesized parameters may only be used with a trait");
|
||||
convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data)
|
||||
}
|
||||
@ -276,7 +277,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
|
||||
prohibit_projections(this.tcx(), &assoc_bindings);
|
||||
|
||||
create_substs_for_ast_path(this,
|
||||
path.span,
|
||||
span,
|
||||
decl_generics,
|
||||
None,
|
||||
types,
|
||||
@ -625,8 +626,9 @@ pub fn instantiate_trait_ref<'tcx>(
|
||||
fn object_path_to_poly_trait_ref<'a,'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
trait_def_id: ast::DefId,
|
||||
path: &ast::Path,
|
||||
trait_segment: &ast::PathSegment,
|
||||
mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
|
||||
-> ty::PolyTraitRef<'tcx>
|
||||
{
|
||||
@ -637,10 +639,10 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
|
||||
let mut tmp = Vec::new();
|
||||
let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
|
||||
&shifted_rscope,
|
||||
path.span,
|
||||
span,
|
||||
trait_def_id,
|
||||
None,
|
||||
path.segments.last().unwrap(),
|
||||
trait_segment,
|
||||
Some(&mut tmp)));
|
||||
projections.extend(tmp.into_iter().map(ty::Binder));
|
||||
trait_ref
|
||||
@ -824,78 +826,28 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ast_path_to_ty<'tcx>(
|
||||
fn ast_path_to_ty<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
span: Span,
|
||||
did: ast::DefId,
|
||||
path: &ast::Path)
|
||||
-> TypeAndSubsts<'tcx>
|
||||
item_segment: &ast::PathSegment)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
let ty::TypeScheme {
|
||||
generics,
|
||||
ty: decl_ty
|
||||
} = this.get_item_type_scheme(did);
|
||||
|
||||
let substs = ast_path_substs_for_ty(this,
|
||||
rscope,
|
||||
&generics,
|
||||
path);
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
TypeAndSubsts { substs: substs, ty: ty }
|
||||
}
|
||||
let substs = ast_path_substs_for_ty(this, rscope, span, &generics, item_segment);
|
||||
|
||||
/// Converts the given AST type to a built-in type. A "built-in type" is, at
|
||||
/// present, either a core numeric type, a string, or `Box`.
|
||||
pub fn ast_ty_to_builtin_ty<'tcx>(
|
||||
this: &AstConv<'tcx>,
|
||||
rscope: &RegionScope,
|
||||
ast_ty: &ast::Ty)
|
||||
-> Option<Ty<'tcx>> {
|
||||
match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
|
||||
Some(typ) => return Some(typ),
|
||||
None => {}
|
||||
// FIXME(#12938): This is a hack until we have full support for DST.
|
||||
if Some(did) == this.tcx().lang_items.owned_box() {
|
||||
assert_eq!(substs.types.len(TypeSpace), 1);
|
||||
return ty::mk_uniq(this.tcx(), *substs.types.get(TypeSpace, 0));
|
||||
}
|
||||
|
||||
match ast_ty.node {
|
||||
ast::TyPath(ref path) => {
|
||||
let a_def = match this.tcx().def_map.borrow().get(&ast_ty.id) {
|
||||
None => {
|
||||
this.tcx()
|
||||
.sess
|
||||
.span_bug(ast_ty.span,
|
||||
&format!("unbound path {}",
|
||||
path.repr(this.tcx())))
|
||||
}
|
||||
Some(&d) => d
|
||||
};
|
||||
|
||||
// FIXME(#12938): This is a hack until we have full support for
|
||||
// DST.
|
||||
match a_def {
|
||||
def::DefTy(did, _) |
|
||||
def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
|
||||
let ty = ast_path_to_ty(this, rscope, did, path).ty;
|
||||
match ty.sty {
|
||||
ty::ty_struct(struct_def_id, ref substs) => {
|
||||
assert_eq!(struct_def_id, did);
|
||||
assert_eq!(substs.types.len(TypeSpace), 1);
|
||||
let referent_ty = *substs.types.get(TypeSpace, 0);
|
||||
Some(ty::mk_uniq(this.tcx(), referent_ty))
|
||||
}
|
||||
_ => {
|
||||
this.tcx().sess.span_bug(
|
||||
path.span,
|
||||
&format!("converting `Box` to `{}`",
|
||||
ty.repr(this.tcx())));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
decl_ty.subst(this.tcx(), &substs)
|
||||
}
|
||||
|
||||
type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
|
||||
@ -919,13 +871,15 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
|
||||
|
||||
match ty.node {
|
||||
ast::TyPath(ref path) => {
|
||||
match this.tcx().def_map.borrow().get(&ty.id) {
|
||||
Some(&def::DefTrait(trait_def_id)) => {
|
||||
let def = this.tcx().def_map.borrow().get(&ty.id).cloned();
|
||||
match def {
|
||||
Some(def::DefTrait(trait_def_id)) => {
|
||||
let mut projection_bounds = Vec::new();
|
||||
let trait_ref = object_path_to_poly_trait_ref(this,
|
||||
rscope,
|
||||
path.span,
|
||||
trait_def_id,
|
||||
path,
|
||||
path.segments.last().unwrap(),
|
||||
&mut projection_bounds);
|
||||
Ok((trait_ref, projection_bounds))
|
||||
}
|
||||
@ -989,21 +943,35 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
|
||||
}
|
||||
|
||||
fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
ast_ty: &ast::Ty,
|
||||
provenance: def::TyParamProvenance,
|
||||
assoc_name: ast::Name)
|
||||
-> Ty<'tcx>
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
ty_path_def: def::Def,
|
||||
item_segment: &ast::PathSegment)
|
||||
-> (Ty<'tcx>, def::Def)
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
let ty_param_def_id = provenance.def_id();
|
||||
check_path_args(tcx, span, slice::ref_slice(item_segment),
|
||||
NO_TPS | NO_REGIONS);
|
||||
let assoc_name = item_segment.identifier.name;
|
||||
|
||||
let ty_param_node_id = if let ty::ty_param(_) = ty.sty {
|
||||
ty_path_def.local_node_id()
|
||||
} else {
|
||||
span_err!(tcx.sess, span, E0223,
|
||||
"ambiguous associated type; specify the type using the syntax \
|
||||
`<{} as Trait>::{}`",
|
||||
ty.user_string(tcx), token::get_name(assoc_name));
|
||||
return (tcx.types.err, ty_path_def);
|
||||
};
|
||||
|
||||
let mut suitable_bounds: Vec<_>;
|
||||
let ty_param_name: ast::Name;
|
||||
{ // contain scope of refcell:
|
||||
let ty_param_defs = tcx.ty_param_defs.borrow();
|
||||
let ty_param_def = &ty_param_defs[ty_param_def_id.node];
|
||||
let ty_param_def = &ty_param_defs[ty_param_node_id];
|
||||
ty_param_name = ty_param_def.name;
|
||||
|
||||
|
||||
// FIXME(#20300) -- search where clauses, not bounds
|
||||
suitable_bounds =
|
||||
traits::transitive_bounds(tcx, &ty_param_def.bounds.trait_bounds)
|
||||
@ -1012,21 +980,21 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
}
|
||||
|
||||
if suitable_bounds.len() == 0 {
|
||||
span_err!(tcx.sess, ast_ty.span, E0220,
|
||||
span_err!(tcx.sess, span, E0220,
|
||||
"associated type `{}` not found for type parameter `{}`",
|
||||
token::get_name(assoc_name),
|
||||
token::get_name(ty_param_name));
|
||||
return this.tcx().types.err;
|
||||
return (this.tcx().types.err, ty_path_def);
|
||||
}
|
||||
|
||||
if suitable_bounds.len() > 1 {
|
||||
span_err!(tcx.sess, ast_ty.span, E0221,
|
||||
span_err!(tcx.sess, span, E0221,
|
||||
"ambiguous associated type `{}` in bounds of `{}`",
|
||||
token::get_name(assoc_name),
|
||||
token::get_name(ty_param_name));
|
||||
|
||||
for suitable_bound in &suitable_bounds {
|
||||
span_note!(this.tcx().sess, ast_ty.span,
|
||||
span_note!(this.tcx().sess, span,
|
||||
"associated type `{}` could derive from `{}`",
|
||||
token::get_name(ty_param_name),
|
||||
suitable_bound.user_string(this.tcx()));
|
||||
@ -1034,7 +1002,32 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
}
|
||||
|
||||
let suitable_bound = suitable_bounds.pop().unwrap().clone();
|
||||
return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name);
|
||||
let trait_did = suitable_bound.0.def_id;
|
||||
|
||||
let ty = this.projected_ty_from_poly_trait_ref(span, suitable_bound, assoc_name);
|
||||
|
||||
let item_did = if trait_did.krate == ast::LOCAL_CRATE {
|
||||
// `ty::trait_items` used below requires information generated
|
||||
// by type collection, which may be in progress at this point.
|
||||
match this.tcx().map.expect_item(trait_did.node).node {
|
||||
ast::ItemTrait(_, _, _, ref trait_items) => {
|
||||
trait_items.iter().filter_map(|i| {
|
||||
if let ast::TypeTraitItem(ref assoc) = *i {
|
||||
if assoc.ty_param.ident.name == assoc_name {
|
||||
return Some(ast_util::local_def(assoc.ty_param.id));
|
||||
}
|
||||
}
|
||||
None
|
||||
}).next().expect("missing associated type")
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
} else {
|
||||
let trait_items = ty::trait_items(this.tcx(), trait_did);
|
||||
let item = trait_items.iter().find(|i| i.name() == assoc_name);
|
||||
item.expect("missing associated type").def_id()
|
||||
};
|
||||
(ty, def::DefAssociatedTy(trait_did, item_did))
|
||||
}
|
||||
|
||||
fn trait_defines_associated_type_named(this: &AstConv,
|
||||
@ -1058,6 +1051,9 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
{
|
||||
let tcx = this.tcx();
|
||||
|
||||
check_path_args(tcx, span, slice::ref_slice(item_segment),
|
||||
NO_TPS | NO_REGIONS);
|
||||
|
||||
let self_ty = if let Some(ty) = opt_self_ty {
|
||||
ast_ty_to_ty(this, rscope, ty)
|
||||
} else {
|
||||
@ -1081,9 +1077,6 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
|
||||
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
|
||||
|
||||
// `<T as Trait>::U<V>` shouldn't parse right now.
|
||||
assert!(item_segment.parameters.is_empty());
|
||||
|
||||
this.projected_ty(span, trait_ref, item_segment.identifier.name)
|
||||
}
|
||||
|
||||
@ -1146,164 +1139,184 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
|
||||
ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
|
||||
drop(ast_ty_to_ty_cache);
|
||||
|
||||
let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
|
||||
match ast_ty.node {
|
||||
ast::TyVec(ref ty) => {
|
||||
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
|
||||
}
|
||||
ast::TyObjectSum(ref ty, ref bounds) => {
|
||||
match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[..]) {
|
||||
Ok((trait_ref, projection_bounds)) => {
|
||||
trait_ref_to_object_type(this,
|
||||
rscope,
|
||||
ast_ty.span,
|
||||
trait_ref,
|
||||
projection_bounds,
|
||||
&bounds[..])
|
||||
}
|
||||
Err(ErrorReported) => {
|
||||
this.tcx().types.err
|
||||
}
|
||||
let typ = match ast_ty.node {
|
||||
ast::TyVec(ref ty) => {
|
||||
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
|
||||
}
|
||||
ast::TyObjectSum(ref ty, ref bounds) => {
|
||||
match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) {
|
||||
Ok((trait_ref, projection_bounds)) => {
|
||||
trait_ref_to_object_type(this,
|
||||
rscope,
|
||||
ast_ty.span,
|
||||
trait_ref,
|
||||
projection_bounds,
|
||||
bounds)
|
||||
}
|
||||
}
|
||||
ast::TyPtr(ref mt) => {
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
|
||||
mutbl: mt.mutbl
|
||||
})
|
||||
}
|
||||
ast::TyRptr(ref region, ref mt) => {
|
||||
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
|
||||
debug!("ty_rptr r={}", r.repr(this.tcx()));
|
||||
let rscope1 =
|
||||
&ObjectLifetimeDefaultRscope::new(
|
||||
rscope,
|
||||
Some(ty::ObjectLifetimeDefault::Specific(r)));
|
||||
let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
|
||||
ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
|
||||
}
|
||||
ast::TyTup(ref fields) => {
|
||||
let flds = fields.iter()
|
||||
.map(|t| ast_ty_to_ty(this, rscope, &**t))
|
||||
.collect();
|
||||
ty::mk_tup(tcx, flds)
|
||||
}
|
||||
ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
|
||||
ast::TyBareFn(ref bf) => {
|
||||
if bf.decl.variadic && bf.abi != abi::C {
|
||||
span_err!(tcx.sess, ast_ty.span, E0222,
|
||||
"variadic function must have C calling convention");
|
||||
Err(ErrorReported) => {
|
||||
this.tcx().types.err
|
||||
}
|
||||
let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
|
||||
ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
|
||||
}
|
||||
ast::TyPolyTraitRef(ref bounds) => {
|
||||
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..])
|
||||
}
|
||||
ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => {
|
||||
let a_def = match tcx.def_map.borrow().get(&ast_ty.id) {
|
||||
None => {
|
||||
tcx.sess
|
||||
.span_bug(ast_ty.span,
|
||||
&format!("unbound path {}",
|
||||
ast_ty.repr(tcx)))
|
||||
}
|
||||
Some(&d) => d
|
||||
};
|
||||
match a_def {
|
||||
def::DefTrait(trait_def_id) => {
|
||||
// N.B. this case overlaps somewhat with
|
||||
// TyObjectSum, see that fn for details
|
||||
let mut projection_bounds = Vec::new();
|
||||
|
||||
let trait_ref = object_path_to_poly_trait_ref(this,
|
||||
rscope,
|
||||
trait_def_id,
|
||||
path,
|
||||
&mut projection_bounds);
|
||||
|
||||
trait_ref_to_object_type(this, rscope, ast_ty.span,
|
||||
trait_ref, projection_bounds, &[])
|
||||
}
|
||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||
ast_path_to_ty(this, rscope, did, path).ty
|
||||
}
|
||||
def::DefTyParam(space, index, _, name) => {
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
ty::mk_param(tcx, space, index, name)
|
||||
}
|
||||
def::DefSelfTy(_) => {
|
||||
// n.b.: resolve guarantees that the this type only appears in a
|
||||
// trait, which we rely upon in various places when creating
|
||||
// substs
|
||||
check_path_args(tcx, path, NO_TPS | NO_REGIONS);
|
||||
ty::mk_self_type(tcx)
|
||||
}
|
||||
def::DefMod(id) => {
|
||||
span_fatal!(tcx.sess, ast_ty.span, E0247,
|
||||
"found module name used as a type: {}",
|
||||
tcx.map.node_to_string(id.node));
|
||||
}
|
||||
def::DefPrimTy(_) => {
|
||||
panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
|
||||
}
|
||||
def::DefAssociatedTy(trait_did, _) => {
|
||||
let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node {
|
||||
Some(&*qpath.self_type)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
qpath_to_ty(this, rscope, ast_ty.span, opt_self_ty, trait_did,
|
||||
&path.segments[path.segments.len()-2],
|
||||
path.segments.last().unwrap())
|
||||
}
|
||||
def::DefAssociatedPath(provenance, assoc_ident) => {
|
||||
associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
|
||||
}
|
||||
_ => {
|
||||
span_fatal!(tcx.sess, ast_ty.span, E0248,
|
||||
"found value name used \
|
||||
as a type: {:?}",
|
||||
a_def);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TyFixedLengthVec(ref ty, ref e) => {
|
||||
match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
|
||||
Ok(ref r) => {
|
||||
match *r {
|
||||
const_eval::const_int(i) =>
|
||||
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
|
||||
Some(i as uint)),
|
||||
const_eval::const_uint(i) =>
|
||||
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
|
||||
Some(i as uint)),
|
||||
_ => {
|
||||
span_fatal!(tcx.sess, ast_ty.span, E0249,
|
||||
"expected constant expr for array length");
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ref r) => {
|
||||
span_fatal!(tcx.sess, ast_ty.span, E0250,
|
||||
"expected constant expr for array \
|
||||
length: {}",
|
||||
*r);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TyTypeof(ref _e) => {
|
||||
tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
|
||||
}
|
||||
ast::TyInfer => {
|
||||
// TyInfer also appears as the type of arguments or return
|
||||
// values in a ExprClosure, or as
|
||||
// the type of local variables. Both of these cases are
|
||||
// handled specially and will not descend into this routine.
|
||||
this.ty_infer(ast_ty.span)
|
||||
}
|
||||
}
|
||||
});
|
||||
ast::TyPtr(ref mt) => {
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: ast_ty_to_ty(this, rscope, &*mt.ty),
|
||||
mutbl: mt.mutbl
|
||||
})
|
||||
}
|
||||
ast::TyRptr(ref region, ref mt) => {
|
||||
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
|
||||
debug!("ty_rptr r={}", r.repr(this.tcx()));
|
||||
let rscope1 =
|
||||
&ObjectLifetimeDefaultRscope::new(
|
||||
rscope,
|
||||
Some(ty::ObjectLifetimeDefault::Specific(r)));
|
||||
let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
|
||||
ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
|
||||
}
|
||||
ast::TyTup(ref fields) => {
|
||||
let flds = fields.iter()
|
||||
.map(|t| ast_ty_to_ty(this, rscope, &**t))
|
||||
.collect();
|
||||
ty::mk_tup(tcx, flds)
|
||||
}
|
||||
ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
|
||||
ast::TyBareFn(ref bf) => {
|
||||
if bf.decl.variadic && bf.abi != abi::C {
|
||||
span_err!(tcx.sess, ast_ty.span, E0222,
|
||||
"variadic function must have C calling convention");
|
||||
}
|
||||
let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
|
||||
ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
|
||||
}
|
||||
ast::TyPolyTraitRef(ref bounds) => {
|
||||
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
|
||||
}
|
||||
ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => {
|
||||
let result = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
|
||||
(d, 0)
|
||||
} else if let Some(d) = tcx.partial_def_map.borrow().get(&ast_ty.id) {
|
||||
(d.base_type, (d.extra_associated_types + 1) as usize)
|
||||
} else {
|
||||
tcx.sess.span_bug(ast_ty.span,
|
||||
&format!("unbound path {}", ast_ty.repr(tcx)))
|
||||
};
|
||||
let (base_def, max_depth) = result;
|
||||
let span = ast_ty.span; // Could be more granular.
|
||||
let segments = &path.segments[..path.segments.len()-max_depth];
|
||||
let base_ty = match base_def {
|
||||
def::DefTrait(trait_def_id) => {
|
||||
// N.B. this case overlaps somewhat with
|
||||
// TyObjectSum, see that fn for details
|
||||
let mut projection_bounds = Vec::new();
|
||||
|
||||
let trait_ref = object_path_to_poly_trait_ref(this,
|
||||
rscope,
|
||||
span,
|
||||
trait_def_id,
|
||||
segments.last().unwrap(),
|
||||
&mut projection_bounds);
|
||||
|
||||
check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS);
|
||||
trait_ref_to_object_type(this, rscope, span, trait_ref,
|
||||
projection_bounds, &[])
|
||||
}
|
||||
def::DefTy(did, _) | def::DefStruct(did) => {
|
||||
check_path_args(tcx, span, segments.init(), NO_TPS | NO_REGIONS);
|
||||
ast_path_to_ty(this, rscope, span, did, segments.last().unwrap())
|
||||
}
|
||||
def::DefTyParam(space, index, _, name) => {
|
||||
check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS);
|
||||
ty::mk_param(tcx, space, index, name)
|
||||
}
|
||||
def::DefSelfTy(_) => {
|
||||
// n.b.: resolve guarantees that the this type only appears in a
|
||||
// trait, which we rely upon in various places when creating
|
||||
// substs
|
||||
check_path_args(tcx, span, segments, NO_TPS | NO_REGIONS);
|
||||
ty::mk_self_type(tcx)
|
||||
}
|
||||
def::DefAssociatedTy(trait_did, _) => {
|
||||
let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node {
|
||||
Some(&*qpath.self_type)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
check_path_args(tcx, span, &segments[..segments.len()-2],
|
||||
NO_TPS | NO_REGIONS);
|
||||
qpath_to_ty(this, rscope, span, opt_self_ty, trait_did,
|
||||
&segments[segments.len()-2],
|
||||
segments.last().unwrap())
|
||||
}
|
||||
def::DefMod(id) => {
|
||||
tcx.sess.span_bug(span,
|
||||
&format!("found module name used as a type: {}",
|
||||
tcx.map.node_to_string(id.node)));
|
||||
}
|
||||
def::DefPrimTy(prim_ty) => {
|
||||
prim_ty_to_ty(tcx, span, segments, prim_ty)
|
||||
}
|
||||
_ => {
|
||||
span_fatal!(tcx.sess, span, E0248,
|
||||
"found value name used as a type: {:?}", base_def);
|
||||
}
|
||||
};
|
||||
|
||||
// If any associated type segments remain, attempt to resolve them.
|
||||
let mut ty = base_ty;
|
||||
let mut def = base_def;
|
||||
for depth in (0..max_depth).rev() {
|
||||
if ty.sty == ty::ty_err {
|
||||
break;
|
||||
}
|
||||
// This is pretty bad (it will fail except for T::A and Self::A).
|
||||
let segment = &path.segments[path.segments.len()-depth-1];
|
||||
let (a_ty, a_def) = associated_path_def_to_ty(this, span,
|
||||
ty, def, segment);
|
||||
ty = a_ty;
|
||||
def = a_def;
|
||||
}
|
||||
|
||||
if max_depth != 0 && ty.sty != ty::ty_err {
|
||||
// Write back the new resolution.
|
||||
tcx.def_map.borrow_mut().insert(ast_ty.id, def);
|
||||
}
|
||||
|
||||
ty
|
||||
}
|
||||
ast::TyFixedLengthVec(ref ty, ref e) => {
|
||||
match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
|
||||
Ok(r) => {
|
||||
match r {
|
||||
const_eval::const_int(i) =>
|
||||
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
|
||||
Some(i as uint)),
|
||||
const_eval::const_uint(i) =>
|
||||
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
|
||||
Some(i as uint)),
|
||||
_ => {
|
||||
span_fatal!(tcx.sess, ast_ty.span, E0249,
|
||||
"expected constant expr for array length");
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(r) => {
|
||||
span_fatal!(tcx.sess, ast_ty.span, E0250,
|
||||
"expected constant expr for array length: {}", r);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::TyTypeof(ref _e) => {
|
||||
tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
|
||||
}
|
||||
ast::TyInfer => {
|
||||
// TyInfer also appears as the type of arguments or return
|
||||
// values in a ExprClosure, or as
|
||||
// the type of local variables. Both of these cases are
|
||||
// handled specially and will not descend into this routine.
|
||||
this.ty_infer(ast_ty.span)
|
||||
}
|
||||
};
|
||||
|
||||
tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
|
||||
return typ;
|
||||
|
@ -1613,7 +1613,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
generics.regions.get_slice(TypeSpace));
|
||||
Substs::new_type(tps, rps)
|
||||
} else {
|
||||
astconv::ast_path_substs_for_ty(self, self, &generics, path)
|
||||
astconv::ast_path_substs_for_ty(self, self,
|
||||
path.span,
|
||||
&generics,
|
||||
path.segments.last().unwrap())
|
||||
};
|
||||
|
||||
let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
|
||||
@ -4632,7 +4635,6 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
def::DefTrait(_) |
|
||||
def::DefTy(..) |
|
||||
def::DefAssociatedTy(..) |
|
||||
def::DefAssociatedPath(..) |
|
||||
def::DefPrimTy(_) |
|
||||
def::DefTyParam(..) |
|
||||
def::DefMod(..) |
|
||||
@ -4731,7 +4733,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
def::DefVariant(..) |
|
||||
def::DefTy(..) |
|
||||
def::DefAssociatedTy(..) |
|
||||
def::DefAssociatedPath(..) |
|
||||
def::DefTrait(..) |
|
||||
def::DefPrimTy(..) |
|
||||
def::DefTyParam(..) => {
|
||||
|
@ -8,13 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
struct Foo {
|
||||
x: isize
|
||||
}
|
||||
|
||||
impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module
|
||||
impl Fo { //~ ERROR use of undeclared type name `Fo`
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module
|
||||
impl B { //~ ERROR use of undeclared type name `B`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -14,7 +14,7 @@ mod a {
|
||||
trait A {
|
||||
}
|
||||
|
||||
impl A for a { //~ERROR found module name used as a type
|
||||
impl A for a { //~ ERROR use of undeclared type name `a`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -8,9 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
impl<T> Option<T> { //~ERROR inherent implementations are not allowed for types not defined in the current module
|
||||
// FIXME(eddyb/UFCS) This should have a nicer error, but that's not possible just yet.
|
||||
impl<T> Option<T> { //~ ERROR use of undeclared type name `Option`
|
||||
pub fn foo(&self) { }
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user