From 004df413aa35b3d610faf231682cfbae5d4eeb46 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Fri, 30 Jan 2015 10:09:44 +0200 Subject: [PATCH] syntax: don't use TraitRef in QPath. --- src/librustc/lint/context.rs | 5 ++ src/librustc/lint/mod.rs | 1 + src/librustc/metadata/encoder.rs | 5 +- src/librustc/middle/dead.rs | 5 ++ src/librustc/middle/ty.rs | 34 ++++----- src/librustc_back/svh.rs | 5 ++ src/librustc_privacy/lib.rs | 5 ++ src/librustc_resolve/lib.rs | 74 ++++++++----------- src/librustc_trans/save/mod.rs | 4 +- src/librustc_typeck/astconv.rs | 28 ++++--- src/librustc_typeck/check/mod.rs | 14 ++-- src/librustc_typeck/check/wf.rs | 4 +- src/librustc_typeck/coherence/impls.rs | 4 +- src/librustc_typeck/coherence/mod.rs | 38 +++------- src/librustc_typeck/collect.rs | 4 +- src/librustdoc/clean/mod.rs | 2 +- src/libsyntax/ast.rs | 8 +- src/libsyntax/ast_util.rs | 9 ++- src/libsyntax/fold.rs | 8 +- src/libsyntax/parse/parser.rs | 8 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 20 +++-- .../compile-fail/ufcs-qpath-missing-params.rs | 2 +- 23 files changed, 143 insertions(+), 146 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index d344ee8c881..81fb1c8e913 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -717,6 +717,11 @@ fn visit_path(&mut self, p: &ast::Path, id: ast::NodeId) { visit::walk_path(self, p); } + fn visit_qpath(&mut self, p: &ast::QPath, id: ast::NodeId) { + run_lints!(self, check_qpath, p, id); + visit::walk_qpath(self, p); + } + fn visit_attribute(&mut self, attr: &ast::Attribute) { run_lints!(self, check_attribute, attr); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 021827b0101..1e2ddb7db0b 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -157,6 +157,7 @@ fn check_lifetime_def(&mut self, _: &Context, _: &ast::LifetimeDef) { } fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { } fn check_mac(&mut self, _: &Context, _: &ast::Mac) { } fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { } + fn check_qpath(&mut self, _: &Context, _: &ast::QPath, _: ast::NodeId) { } fn check_attribute(&mut self, _: &Context, _: &ast::Attribute) { } /// Called when entering a syntax node that can have lint attributes such diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index e6f5c36a2f8..1a695baf721 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1241,9 +1241,8 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder, } rbml_w.end_tag(); } - if let Some(ref ast_trait_ref) = *opt_trait { - let trait_ref = ty::node_id_to_trait_ref( - tcx, ast_trait_ref.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id); encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref); } encode_path(rbml_w, path.clone()); diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index ff78deb8d12..4f9b900a5f8 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -306,6 +306,11 @@ fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) { visit::walk_path(self, path); } + fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { + self.lookup_and_handle_definition(&id); + visit::walk_qpath(self, qpath); + } + fn visit_item(&mut self, _: &ast::Item) { // Do not recurse into items. These items will be added to the // worklist and recursed into manually if necessary. diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3d059e27c52..c4fe3f4df02 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -709,7 +709,7 @@ pub struct ctxt<'tcx> { pub impl_trait_cache: RefCell>>>>, - pub trait_refs: RefCell>>>, + pub impl_trait_refs: RefCell>>>, pub trait_defs: RefCell>>>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its @@ -2449,7 +2449,7 @@ pub fn mk_ctxt<'tcx>(s: Session, region_maps: region_maps, node_types: RefCell::new(FnvHashMap()), item_substs: RefCell::new(NodeMap()), - trait_refs: RefCell::new(NodeMap()), + impl_trait_refs: RefCell::new(NodeMap()), trait_defs: RefCell::new(DefIdMap()), predicates: RefCell::new(DefIdMap()), object_cast_map: RefCell::new(NodeMap()), @@ -4174,12 +4174,12 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>, } } -pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) +pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Rc> { - match cx.trait_refs.borrow().get(&id) { + match cx.impl_trait_refs.borrow().get(&id) { Some(ty) => ty.clone(), None => cx.sess.bug( - &format!("node_id_to_trait_ref: no trait ref for node `{}`", + &format!("impl_id_to_trait_ref: no trait ref for impl `{}`", cx.map.node_to_string(id))) } } @@ -5116,25 +5116,19 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) memoized(&cx.impl_trait_cache, id, |id: ast::DefId| { if id.krate == ast::LOCAL_CRATE { debug!("(impl_trait_ref) searching for trait impl {:?}", id); - match cx.map.find(id.node) { - Some(ast_map::NodeItem(item)) => { - match item.node { - ast::ItemImpl(_, _, _, ref opt_trait, _, _) => { - match opt_trait { - &Some(ref t) => { - let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id); - Some(trait_ref) - } - &None => None - } - } + if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) { + if let ast::ItemImpl(_, _, _, ref opt_trait, _, _) = item.node { + opt_trait.as_ref().map(|_| { + ty::impl_id_to_trait_ref(cx, id.node) + }) + } else { + None ast::ItemDefaultImpl(_, ref ast_trait_ref) => { Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id)) } - _ => None - } } - _ => None + } else { + None } } else { csearch::get_impl_trait(cx, id) diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 2fc43ab26b5..af886ed25ab 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -194,6 +194,7 @@ enum SawAbiComponent<'a> { SawVariant, SawExplicitSelf, SawPath, + SawQPath, SawOptLifetimeRef, SawBlock, SawPat, @@ -485,6 +486,10 @@ fn visit_path(&mut self, path: &Path, _: ast::NodeId) { SawPath.hash(self.st); visit::walk_path(self, path) } + fn visit_qpath(&mut self, qpath: &QPath, _: ast::NodeId) { + SawQPath.hash(self.st); visit::walk_qpath(self, qpath) + } + fn visit_block(&mut self, b: &Block) { SawBlock.hash(self.st); visit::walk_block(self, b) } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 838ba9c658c..1f8ae3fbbcb 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1021,6 +1021,11 @@ fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) { self.check_path(path.span, id, path.segments.last().unwrap().identifier); visit::walk_path(self, path); } + + fn visit_qpath(&mut self, qpath: &ast::QPath, id: ast::NodeId) { + self.check_path(qpath.trait_path.span, id, qpath.item_path.identifier); + visit::walk_qpath(self, qpath); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 55ad52762e0..1380e236725 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2875,8 +2875,7 @@ fn resolve_item(&mut self, item: &Item) { this.resolve_type_parameters(&generics.ty_params); this.resolve_where_clause(&generics.where_clause); - this.resolve_type_parameter_bounds(item.id, bounds, - TraitDerivation); + this.resolve_type_parameter_bounds(bounds, TraitDerivation); for trait_item in &(*trait_items) { // Create a new rib for the trait_item-specific type @@ -3141,8 +3140,7 @@ fn resolve_type_parameter(&mut self, type_parameter: &TyParam) { self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span); for bound in &*type_parameter.bounds { - self.resolve_type_parameter_bound(type_parameter.id, bound, - TraitBoundingTypeParameter); + self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); } match type_parameter.default { Some(ref ty) => self.resolve_type(&**ty), @@ -3151,41 +3149,33 @@ fn resolve_type_parameter(&mut self, } fn resolve_type_parameter_bounds(&mut self, - id: NodeId, type_parameter_bounds: &OwnedSlice, reference_type: TraitReferenceType) { for type_parameter_bound in &**type_parameter_bounds { - self.resolve_type_parameter_bound(id, type_parameter_bound, - reference_type); + self.resolve_type_parameter_bound(type_parameter_bound, reference_type); } } fn resolve_type_parameter_bound(&mut self, - id: NodeId, type_parameter_bound: &TyParamBound, reference_type: TraitReferenceType) { match *type_parameter_bound { TraitTyParamBound(ref tref, _) => { - self.resolve_poly_trait_reference(id, tref, reference_type) + self.resolve_trait_reference(tref.trait_ref.ref_id, + &tref.trait_ref.path, + reference_type) } RegionTyParamBound(..) => {} } } - fn resolve_poly_trait_reference(&mut self, - id: NodeId, - poly_trait_reference: &PolyTraitRef, - reference_type: TraitReferenceType) { - self.resolve_trait_reference(id, &poly_trait_reference.trait_ref, reference_type) - } - fn resolve_trait_reference(&mut self, id: NodeId, - trait_reference: &TraitRef, + trait_path: &Path, reference_type: TraitReferenceType) { - match self.resolve_path(id, &trait_reference.path, TypeNS, true) { + match self.resolve_path(id, trait_path, TypeNS, true) { None => { - let path_str = self.path_names_to_string(&trait_reference.path); + let path_str = self.path_names_to_string(trait_path); let usage_str = match reference_type { TraitBoundingTypeParameter => "bound type parameter with", TraitImplementation => "implement", @@ -3195,26 +3185,23 @@ fn resolve_trait_reference(&mut self, }; let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str); - self.resolve_error(trait_reference.path.span, &msg[..]); + self.resolve_error(trait_path.span, &msg[..]); } Some(def) => { match def { (DefTrait(_), _) => { debug!("(resolving trait) found trait def: {:?}", def); - self.record_def(trait_reference.ref_id, def); + self.record_def(id, def); } (def, _) => { - self.resolve_error(trait_reference.path.span, - &format!("`{}` is not a trait", - self.path_names_to_string( - &trait_reference.path))); + self.resolve_error(trait_path.span, + &format!("`{}` is not a trait", + self.path_names_to_string(trait_path))); // If it's a typedef, give a note if let DefTy(..) = def { - self.session.span_note( - trait_reference.path.span, - &format!("`type` aliases cannot be used for traits") - ); + self.session.span_note(trait_path.span, + &format!("`type` aliases cannot be used for traits")); } } } @@ -3229,8 +3216,7 @@ fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) { self.resolve_type(&*bound_pred.bounded_ty); for bound in &*bound_pred.bounds { - self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound, - TraitBoundingTypeParameter); + self.resolve_type_parameter_bound(bound, TraitBoundingTypeParameter); } } &ast::WherePredicate::RegionPredicate(_) => {} @@ -3303,14 +3289,16 @@ fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T where result } - fn with_optional_trait_ref(&mut self, id: NodeId, + fn with_optional_trait_ref(&mut self, opt_trait_ref: &Option, f: F) -> T where F: FnOnce(&mut Resolver) -> T, { let new_val = match *opt_trait_ref { Some(ref trait_ref) => { - self.resolve_trait_reference(id, trait_ref, TraitImplementation); + self.resolve_trait_reference(trait_ref.ref_id, + &trait_ref.path, + TraitImplementation); match self.def_map.borrow().get(&trait_ref.ref_id) { Some(def) => { @@ -3345,7 +3333,7 @@ fn resolve_implementation(&mut self, this.resolve_where_clause(&generics.where_clause); // Resolve the trait reference, if necessary. - this.with_optional_trait_ref(id, opt_trait_reference, |this| { + this.with_optional_trait_ref(opt_trait_reference, |this| { // Resolve the self type. this.resolve_type(self_type); @@ -3630,13 +3618,12 @@ fn resolve_type(&mut self, ty: &Ty) { TyObjectSum(ref ty, ref bound_vec) => { self.resolve_type(&**ty); - self.resolve_type_parameter_bounds(ty.id, bound_vec, - TraitBoundingTypeParameter); + self.resolve_type_parameter_bounds(bound_vec, TraitBoundingTypeParameter); } TyQPath(ref qpath) => { self.resolve_type(&*qpath.self_type); - self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath); + self.resolve_trait_reference(ty.id, &qpath.trait_path, TraitQPath); for ty in qpath.item_path.parameters.types() { self.resolve_type(&**ty); } @@ -3646,10 +3633,7 @@ fn resolve_type(&mut self, ty: &Ty) { } TyPolyTraitRef(ref bounds) => { - self.resolve_type_parameter_bounds( - ty.id, - bounds, - TraitObject); + self.resolve_type_parameter_bounds(bounds, TraitObject); visit::walk_ty(self, ty); } _ => { @@ -4439,8 +4423,12 @@ fn resolve_expr(&mut self, expr: &Expr) { ExprPath(ref path) => path, ExprQPath(ref qpath) => { self.resolve_type(&*qpath.self_type); - self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath); - path_from_qpath = qpath.trait_ref.path.clone(); + + // Just make sure the trait is valid, don't record a def. + self.resolve_trait_reference(expr.id, &qpath.trait_path, TraitQPath); + self.def_map.borrow_mut().remove(&expr.id); + + path_from_qpath = qpath.trait_path.clone(); path_from_qpath.segments.push(qpath.item_path.clone()); &path_from_qpath } diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index af891001ea0..c9288665128 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1340,10 +1340,10 @@ fn visit_expr(&mut self, ex: &ast::Expr) { visit::walk_path(self, path); } ast::ExprQPath(ref qpath) => { - let mut path = qpath.trait_ref.path.clone(); + let mut path = qpath.trait_path.clone(); path.segments.push(qpath.item_path.clone()); self.process_path(ex.id, ex.span, &path, None); - visit::walk_qpath(self, ex.span, &**qpath); + visit::walk_qpath(self, &**qpath); } ast::ExprStruct(ref path, ref fields, ref base) => self.process_struct_lit(ex, path, fields, base), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 16a2dbf2687..3c4af12c1f9 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -574,9 +574,10 @@ pub fn instantiate_poly_trait_ref<'tcx>( // lifetimes. Oh well, not there yet. let shifted_rscope = ShiftedRscope::new(rscope); - let trait_ref = - instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref, - self_ty, Some(&mut projections)); + let trait_ref = instantiate_trait_ref(this, &shifted_rscope, + &ast_trait_ref.trait_ref.path, + ast_trait_ref.trait_ref.ref_id, + None, self_ty, Some(&mut projections)); for projection in projections { poly_projections.push(ty::Binder(projection)); @@ -594,26 +595,29 @@ pub fn instantiate_poly_trait_ref<'tcx>( pub fn instantiate_trait_ref<'tcx>( this: &AstConv<'tcx>, rscope: &RegionScope, - ast_trait_ref: &ast::TraitRef, + path: &ast::Path, + path_id: ast::NodeId, + impl_id: Option, self_ty: Option>, projections: Option<&mut Vec>>) -> Rc> { - match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) { + match ::lookup_def_tcx(this.tcx(), path.span, path_id) { def::DefTrait(trait_def_id) => { let trait_ref = ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty, - &ast_trait_ref.path, + path, projections); - this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone()); + if let Some(id) = impl_id { + this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone()); + } trait_ref } _ => { - span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245, - "`{}` is not a trait", - ast_trait_ref.path.user_string(this.tcx())); + span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait", + path.user_string(this.tcx())); } } } @@ -1056,7 +1060,9 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>, let trait_ref = instantiate_trait_ref(this, rscope, - &*qpath.trait_ref, + &qpath.trait_path, + ast_ty.id, + None, Some(self_type), None); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 0430954ad7e..b6003071f8c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3611,13 +3611,10 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, constrain_path_type_parameters(fcx, expr); } ast::ExprQPath(ref qpath) => { - // Require explicit type params for the trait. let self_ty = fcx.to_ty(&*qpath.self_type); - astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None); - let defn = lookup_def(fcx, expr.span, id); let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn); - let mut path = qpath.trait_ref.path.clone(); + let mut path = qpath.trait_path.clone(); path.segments.push(qpath.item_path.clone()); instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty), defn, expr.span, expr.id); @@ -4829,7 +4826,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // to add defaults. If the user provided *too many* types, that's // a problem. for &space in &ParamSpace::all() { - adjust_type_parameters(fcx, span, space, type_defs, &mut substs); + adjust_type_parameters(fcx, span, space, type_defs, + opt_self_ty.is_some(), &mut substs); assert_eq!(substs.types.len(space), type_defs.len(space)); adjust_region_parameters(fcx, span, space, region_defs, &mut substs); @@ -5007,6 +5005,7 @@ fn adjust_type_parameters<'a, 'tcx>( span: Span, space: ParamSpace, defs: &VecPerParamSpace>, + require_type_space: bool, substs: &mut Substs<'tcx>) { let provided_len = substs.types.len(space); @@ -5029,9 +5028,8 @@ fn adjust_type_parameters<'a, 'tcx>( // Nothing specified at all: supply inference variables for // everything. - if provided_len == 0 { - substs.types.replace(space, - fcx.infcx().next_ty_vars(desired.len())); + if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) { + substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len())); return; } diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 399795c6656..e024526d001 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -81,8 +81,8 @@ fn check_item_well_formed(&mut self, item: &ast::Item) { ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => { self.check_impl(item); } - ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => { - let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id); + ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => { + let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id); ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id); match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { Some(ty::BoundSend) | Some(ty::BoundSync) => {} diff --git a/src/librustc_typeck/coherence/impls.rs b/src/librustc_typeck/coherence/impls.rs index e535b86a7bf..e89c96b36e1 100644 --- a/src/librustc_typeck/coherence/impls.rs +++ b/src/librustc_typeck/coherence/impls.rs @@ -28,8 +28,8 @@ struct ImplsChecker<'cx, 'tcx:'cx> { impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v ast::Item) { match item.node { - ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => { - let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id); + ast::ItemImpl(_, _, _, Some(_), _, _) => { + let trait_ref = ty::impl_id_to_trait_ref(self.tcx, item.id); if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { match trait_ref.self_ty().sty { ty::ty_struct(..) | ty::ty_enum(..) => {} diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 7dac1eeb6f1..1913b55f1d8 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -106,19 +106,9 @@ fn visit_item(&mut self, item: &Item) { //debug!("(checking coherence) item '{}'", token::get_ident(item.ident)); - match item.node { - ItemImpl(_, _, _, ref opt_trait, _, _) => { - match opt_trait.clone() { - Some(opt_trait) => { - self.cc.check_implementation(item, &[opt_trait]); - } - None => self.cc.check_implementation(item, &[]) - } - } - _ => { - // Nothing to do. - } - }; + if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node { + self.cc.check_implementation(item, opt_trait.as_ref()) + } visit::walk_item(self, item); } @@ -155,9 +145,7 @@ fn check(&self, krate: &Crate) { self.check_implementations_of_copy(); } - fn check_implementation(&self, - item: &Item, - associated_traits: &[TraitRef]) { + fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) { let tcx = self.crate_context.tcx; let impl_did = local_def(item.id); let self_type = ty::lookup_item_type(tcx, impl_did); @@ -167,9 +155,8 @@ fn check_implementation(&self, let impl_items = self.create_impl_from_item(item); - for associated_trait in associated_traits { - let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx, - associated_trait.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id); debug!("(checking implementation) adding impl for trait '{}', item '{}'", trait_ref.repr(self.crate_context.tcx), token::get_ident(item.ident)); @@ -191,7 +178,7 @@ fn check_implementation(&self, } Some(base_type_def_id) => { // FIXME: Gather up default methods? - if associated_traits.len() == 0 { + if opt_trait.is_none() { self.add_inherent_impl(base_type_def_id, impl_did); } } @@ -289,7 +276,7 @@ fn get_self_type_for_implementation(&self, impl_did: DefId) // Converts an implementation in the AST to a vector of items. fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { - ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => { + ItemImpl(_, _, _, ref opt_trait, _, ref ast_items) => { let mut items: Vec = ast_items.iter() .map(|ast_item| { @@ -304,13 +291,12 @@ fn create_impl_from_item(&self, item: &Item) -> Vec { } }).collect(); - if let Some(ref trait_ref) = *trait_refs { - let ty_trait_ref = ty::node_id_to_trait_ref( - self.crate_context.tcx, - trait_ref.ref_id); + if opt_trait.is_some() { + let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, + item.id); self.instantiate_default_methods(local_def(item.id), - &*ty_trait_ref, + &*trait_ref, &mut items); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 353e8e097a8..65c1d7adf48 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -740,7 +740,9 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) { if let Some(ref trait_ref) = *opt_trait_ref { astconv::instantiate_trait_ref(ccx, &ExplicitRscope, - trait_ref, + &trait_ref.path, + trait_ref.ref_id, + Some(it.id), Some(selfty), None); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d05aa4d2006..8e08c5278d0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1629,7 +1629,7 @@ fn clean(&self, cx: &DocContext) -> Type { Type::QPath { name: self.item_path.identifier.clean(cx), self_type: box self.self_type.clean(cx), - trait_: box self.trait_ref.clean(cx) + trait_: box resolve_type(cx, self.trait_path.clean(cx), 0) } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7c83286f656..5f9776425c3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -782,11 +782,11 @@ pub enum Expr_ { /// /// as SomeTrait>::SomeAssociatedItem /// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~ -/// self_type trait_name item_path +/// self_type trait_path item_path #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct QPath { pub self_type: P, - pub trait_ref: P, + pub trait_path: Path, pub item_path: PathSegment, } @@ -1258,12 +1258,12 @@ pub enum Ty_ { /// /// Type parameters are stored in the Path itself TyPath(Path), + /// A "qualified path", e.g. ` as SomeTrait>::SomeType` + TyQPath(P), /// Something like `A+B`. Note that `B` must always be a path. TyObjectSum(P, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` TyPolyTraitRef(TyParamBounds), - /// A "qualified path", e.g. ` as SomeTrait>::SomeType` - TyQPath(P), /// No-op; kept solely so that we can pretty-print faithfully TyParen(P), /// Unused for now diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 6ea37aaf72c..f207efc5b6c 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -561,13 +561,18 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) { visit::walk_trait_item(self, tm); } - fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { + fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) { self.operation.visit_id(lifetime.id); } - fn visit_lifetime_def(&mut self, def: &'v LifetimeDef) { + fn visit_lifetime_def(&mut self, def: &LifetimeDef) { self.visit_lifetime_ref(&def.lifetime); } + + fn visit_trait_ref(&mut self, trait_ref: &TraitRef) { + self.operation.visit_id(trait_ref.ref_id); + visit::walk_trait_ref(self, trait_ref); + } } pub fn visit_ids_for_inlined_item(item: &InlinedItem, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index ae4d2a80045..c0421fb6f1c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -429,13 +429,13 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), TyPath(path) => TyPath(fld.fold_path(path)), + TyQPath(qpath) => { + TyQPath(fld.fold_qpath(qpath)) + } TyObjectSum(ty, bounds) => { TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds)) } - TyQPath(qpath) => { - TyQPath(fld.fold_qpath(qpath)) - } TyFixedLengthVec(ty, e) => { TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e)) } @@ -454,7 +454,7 @@ pub fn noop_fold_qpath(qpath: P, fld: &mut T) -> P { qpath.map(|qpath| { QPath { self_type: fld.fold_ty(qpath.self_type), - trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)), + trait_path: fld.fold_path(qpath.trait_path), item_path: PathSegment { identifier: fld.fold_ident(qpath.item_path.identifier), parameters: fld.fold_path_parameters(qpath.item_path.parameters), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bcef7238d7f..b2f59725855 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1525,13 +1525,13 @@ pub fn parse_ty(&mut self) -> P { // QUALIFIED PATH `::item` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); let item_name = self.parse_ident(); TyQPath(P(QPath { self_type: self_type, - trait_ref: P(trait_ref), + trait_path: trait_path, item_path: ast::PathSegment { identifier: item_name, parameters: ast::PathParameters::none() @@ -2220,7 +2220,7 @@ pub fn parse_bottom_expr(&mut self) -> P { // QUALIFIED PATH `::item::<'a, T>` let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); - let trait_ref = self.parse_trait_ref(); + let trait_path = self.parse_path(LifetimeAndTypesWithoutColons); self.expect(&token::Gt); self.expect(&token::ModSep); let item_name = self.parse_ident(); @@ -2240,7 +2240,7 @@ pub fn parse_bottom_expr(&mut self) -> P { let hi = self.span.hi; return self.mk_expr(lo, hi, ExprQPath(P(QPath { self_type: self_type, - trait_ref: P(trait_ref), + trait_path: trait_path, item_path: ast::PathSegment { identifier: item_name, parameters: parameters diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 752d34a19c6..3cfb90a3e68 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2047,7 +2047,7 @@ fn print_qpath(&mut self, try!(self.print_type(&*qpath.self_type)); try!(space(&mut self.s)); try!(self.word_space("as")); - try!(self.print_trait_ref(&*qpath.trait_ref)); + try!(self.print_path(&qpath.trait_path, false)); try!(word(&mut self.s, ">")); try!(word(&mut self.s, "::")); try!(self.print_ident(qpath.item_path.identifier)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4586495227d..4e90adea90c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -125,8 +125,8 @@ fn visit_mac(&mut self, _mac: &'v Mac) { fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) { walk_path(self, path) } - fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) { - walk_qpath(self, qpath_span, qpath) + fn visit_qpath(&mut self, qpath: &'v QPath, _id: ast::NodeId) { + walk_qpath(self, qpath) } fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) @@ -402,13 +402,13 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { TyPath(ref path) => { visitor.visit_path(path, typ.id); } + TyQPath(ref qpath) => { + visitor.visit_qpath(&**qpath, typ.id); + } TyObjectSum(ref ty, ref bounds) => { visitor.visit_ty(&**ty); walk_ty_param_bounds_helper(visitor, bounds); } - TyQPath(ref qpath) => { - visitor.visit_qpath(typ.span, &**qpath); - } TyFixedLengthVec(ref ty, ref expression) => { visitor.visit_ty(&**ty); visitor.visit_expr(&**expression) @@ -436,12 +436,10 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { } } -pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, - qpath_span: Span, - qpath: &'v QPath) { +pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath) { visitor.visit_ty(&*qpath.self_type); - visitor.visit_trait_ref(&*qpath.trait_ref); - visitor.visit_path_segment(qpath_span, &qpath.item_path); + walk_path(visitor, &qpath.trait_path); + visitor.visit_path_segment(qpath.trait_path.span, &qpath.item_path); } pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, @@ -873,7 +871,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_path(path, expression.id) } ExprQPath(ref qpath) => { - visitor.visit_qpath(expression.span, &**qpath) + visitor.visit_qpath(&**qpath, expression.id) } ExprBreak(_) | ExprAgain(_) => {} ExprRet(ref optional_expression) => { diff --git a/src/test/compile-fail/ufcs-qpath-missing-params.rs b/src/test/compile-fail/ufcs-qpath-missing-params.rs index f4e18265fd9..b3fe178dc45 100644 --- a/src/test/compile-fail/ufcs-qpath-missing-params.rs +++ b/src/test/compile-fail/ufcs-qpath-missing-params.rs @@ -12,5 +12,5 @@ fn main() { ::into_cow("foo".to_string()); - //~^ ERROR wrong number of type arguments: expected 1, found 0 + //~^ ERROR too few type parameters provided: expected 1 parameter(s) } -- GitLab