diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs index d45c18efee7..621a231ed7d 100644 --- a/src/librustc/middle/astconv_util.rs +++ b/src/librustc/middle/astconv_util.rs @@ -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> { 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 } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 37586b08b36..f7d34f0056b 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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)), diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index 191672775f2..e1794cc0c8a 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -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 /* 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 +/// +/// ::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>; +pub type PartialDefMap = RefCell>; // This is the replacement export map. It maps a module to all of the exports // within. pub type ExportMap = NodeMap>; @@ -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(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) | diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 59e090a6037..57aac8f98b6 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c4fe3f4df02..2b0d032aa6d 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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, @@ -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()), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index b12f05d7c50..b5933ca11ba 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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, diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index cc47090198b..fefb3c5fe7d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b211681992b..4a57dd0912e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -935,6 +935,7 @@ struct Resolver<'a, 'tcx:'a> { primitive_type_table: PrimitiveTypeTable, def_map: DefMap, + partial_def_map: PartialDefMap, freevars: RefCell, freevars_seen: RefCell>, 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, 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, diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 531700b9563..0ba7bd84603 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -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(_) | diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 9dbcbc8b1a2..196686a70d1 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -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 {:?} \ diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8eb75ece4a1..bc0986eff1f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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::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> { - 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>); @@ -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)); - // `::U` 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; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9d303f492eb..f797d2b6fe7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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(..) => { diff --git a/src/test/compile-fail/issue-7607-1.rs b/src/test/compile-fail/issue-7607-1.rs index 48fc393d0da..4ac90177609 100644 --- a/src/test/compile-fail/issue-7607-1.rs +++ b/src/test/compile-fail/issue-7607-1.rs @@ -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() {} } diff --git a/src/test/compile-fail/issue-8767.rs b/src/test/compile-fail/issue-8767.rs index 6c5bac5e0cb..2ef0a75f77b 100644 --- a/src/test/compile-fail/issue-8767.rs +++ b/src/test/compile-fail/issue-8767.rs @@ -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() { diff --git a/src/test/compile-fail/trait-impl-for-module.rs b/src/test/compile-fail/trait-impl-for-module.rs index 28d20483c7e..969b6398fdb 100644 --- a/src/test/compile-fail/trait-impl-for-module.rs +++ b/src/test/compile-fail/trait-impl-for-module.rs @@ -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() { diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs index e621d77a65c..047e4e50c82 100644 --- a/src/test/compile-fail/trait-or-new-type-instead.rs +++ b/src/test/compile-fail/trait-or-new-type-instead.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - -impl Option { //~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 Option { //~ ERROR use of undeclared type name `Option` pub fn foo(&self) { } }