diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index 22b566044288..1e373441e9e8 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -56,6 +56,7 @@ use super::intravisit::Visitor; /// needed. pub trait ItemLikeVisitor<'hir> { fn visit_item(&mut self, item: &'hir Item); + fn visit_impl_item(&mut self, impl_item: &'hir ImplItem); } pub struct DeepVisitor<'v, V: 'v> { @@ -76,4 +77,8 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> fn visit_item(&mut self, item: &'hir Item) { self.visitor.visit_item(item); } + + fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) { + self.visitor.visit_impl_item(impl_item); + } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 04fcf7e84508..eafb7949da38 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -99,6 +99,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } } + fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { + self.visit_impl_item(self.krate.impl_item(item_id)) + } + fn visit_item(&mut self, i: &'ast Item) { debug!("visit_item: {:?}", i); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 50c581057407..78049663afeb 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -797,8 +797,13 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { /// items in the context of the outer item, so enable /// deep-walking. fn visit_nested_item(&mut self, item: hir::ItemId) { - let tcx = self.tcx; - self.visit_item(tcx.map.expect_item(item.id)) + let item = self.tcx.map.expect_item(item.id); + self.visit_item(item) + } + + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + let impl_item = self.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) } fn visit_item(&mut self, it: &hir::Item) { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 2667943bea93..57abf0bdc427 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -330,11 +330,12 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { // or // 2) We are not sure to be live or not // * Implementation of a trait method -struct LifeSeeder { - worklist: Vec +struct LifeSeeder<'k> { + worklist: Vec, + krate: &'k hir::Crate, } -impl<'v> ItemLikeVisitor<'v> for LifeSeeder { +impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> { fn visit_item(&mut self, item: &hir::Item) { let allow_dead_code = has_allow_dead_code_or_lang_attr(&item.attrs); if allow_dead_code { @@ -358,17 +359,22 @@ impl<'v> ItemLikeVisitor<'v> for LifeSeeder { } } } - hir::ItemImpl(.., ref opt_trait, _, ref impl_items) => { - for impl_item in impl_items { + hir::ItemImpl(.., ref opt_trait, _, ref impl_item_ids) => { + for &impl_item_id in impl_item_ids { + let impl_item = self.krate.impl_item(impl_item_id); if opt_trait.is_some() || has_allow_dead_code_or_lang_attr(&impl_item.attrs) { - self.worklist.push(impl_item.id); + self.worklist.push(impl_item_id.id); } } } _ => () } } + + fn visit_impl_item(&mut self, _item: &hir::ImplItem) { + // ignore: we are handling this in `visit_item` above + } } fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -387,7 +393,8 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Seed implemented trait items let mut life_seeder = LifeSeeder { - worklist: worklist + worklist: worklist, + krate: krate, }; krate.visit_all_item_likes(&mut life_seeder); @@ -510,8 +517,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> { /// an error. We could do this also by checking the parents, but /// this is how the code is setup and it seems harmless enough. fn visit_nested_item(&mut self, item: hir::ItemId) { - let tcx = self.tcx; - self.visit_item(tcx.map.expect_item(item.id)) + let item = self.tcx.map.expect_item(item.id); + self.visit_item(item) + } + + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + let impl_item = self.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) } fn visit_item(&mut self, item: &hir::Item) { diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index e5112749c0ee..9dd54457a349 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -17,7 +17,7 @@ use syntax::ast::NodeId; use syntax::attr; use syntax::entry::EntryPointType; use syntax_pos::Span; -use hir::{Item, ItemFn}; +use hir::{Item, ItemFn, ImplItem}; use hir::itemlikevisit::ItemLikeVisitor; struct EntryContext<'a, 'tcx: 'a> { @@ -46,6 +46,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { let at_root = def_key.parent == Some(CRATE_DEF_INDEX); find_item(item, self, at_root); } + + fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) { + // entry fn is never an impl item + } } pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 6fe8442474a9..9b4b1396669a 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -164,6 +164,10 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { } } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + // at present, lang items are always items, not impl items + } } impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 848f4218d884..0a45f895d7df 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -336,6 +336,10 @@ impl<'a, 'v> ItemLikeVisitor<'v> for CollectPrivateImplItemsVisitor<'a> { } } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + // processed in visit_item above + } } pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index c342342d73b7..68d2cceda847 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -141,6 +141,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { self.visit_item(item) } + fn visit_nested_impl_item(&mut self, id: hir::ImplItemId) { + let impl_item = self.hir_map.impl_item(id); + self.visit_impl_item(impl_item) + } + fn visit_item(&mut self, item: &hir::Item) { // Save labels for nested items. let saved_labels_in_fn = replace(&mut self.labels_in_fn, vec![]); diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index d79833998d6c..f8d58c5f2d91 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -239,8 +239,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> { /// nested items in the context of the outer item, so enable /// deep-walking. fn visit_nested_item(&mut self, item: hir::ItemId) { - let tcx = self.tcx; - self.visit_item(tcx.map.expect_item(item.id)) + let item = self.tcx.map.expect_item(item.id); + self.visit_item(item) + } + + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + let impl_item = self.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) } fn visit_item(&mut self, i: &Item) { @@ -449,8 +454,13 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> { /// nested items in the context of the outer item, so enable /// deep-walking. fn visit_nested_item(&mut self, item: hir::ItemId) { - let tcx = self.tcx; - self.visit_item(tcx.map.expect_item(item.id)) + let item = self.tcx.map.expect_item(item.id); + self.visit_item(item) + } + + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + let impl_item = self.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) } fn visit_item(&mut self, item: &hir::Item) { @@ -527,9 +537,10 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // For implementations of traits, check the stability of each item // individually as it's possible to have a stable trait with unstable // items. - hir::ItemImpl(.., Some(ref t), _, ref impl_items) => { + hir::ItemImpl(.., Some(ref t), _, ref impl_item_ids) => { let trait_did = tcx.expect_def(t.ref_id).def_id(); - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = tcx.map.impl_item(impl_item_id); let item = tcx.associated_items(trait_did) .find(|item| item.name == impl_item.name).unwrap(); if warn_about_defns { diff --git a/src/librustc_driver/derive_registrar.rs b/src/librustc_driver/derive_registrar.rs index 605193a0434b..4db620b2bec3 100644 --- a/src/librustc_driver/derive_registrar.rs +++ b/src/librustc_driver/derive_registrar.rs @@ -34,4 +34,8 @@ impl<'v> ItemLikeVisitor<'v> for Finder { self.registrar = Some(item.id); } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } + diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 84489c2e8c67..d66e0f6aba35 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -171,6 +171,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for IfThisChanged<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { self.process_attrs(item.id, &item.attrs); } + + fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { + // handled in `visit_item` above + } } fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 0b0dd596784e..3060e237fc13 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -503,6 +503,12 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has // Each item is hashed independently; ignore nested items. } + fn visit_nested_impl_item(&mut self, impl_item_id: ImplItemId) { + // For now, we hash impl items as part of the containing impl. + let impl_item = self.tcx.map.impl_item(impl_item_id); + self.visit_impl_item(impl_item); + } + fn visit_variant_data(&mut self, s: &'tcx VariantData, name: Name, diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index f6b7abd2ef12..0cd1c88fb877 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -184,6 +184,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'a, 'tcx> { } } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } pub fn check_dirty_clean_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -225,6 +228,9 @@ impl<'a, 'tcx, 'm> ItemLikeVisitor<'tcx> for DirtyCleanMetadataVisitor<'a, 'tcx, } } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } impl<'a, 'tcx, 'm> DirtyCleanMetadataVisitor<'a, 'tcx, 'm> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index bbffe88316b3..2d96eeb8f201 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1177,6 +1177,10 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { } } } + + fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { + // handled in `visit_item` above + } } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b33a7060e375..21bebb2562a1 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -277,8 +277,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { .and_then(|impl_node_id| self.tcx.map.find(impl_node_id)) .map(|node| { if let hir_map::NodeItem(item) = node { - if let hir::ItemImpl(_, _, _, _, _, ref methods) = item.node { - span = methods.first().map(|method| method.span); + if let hir::ItemImpl(_, _, _, _, _, ref impl_item_ids) = item.node { + span = impl_item_ids.first() + .map(|&impl_item_id| { + self.tcx.map.impl_item(impl_item_id) + .span + }); } } }); diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index adcb7842ee1f..724100e02237 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -44,6 +44,10 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { self.with_context(Normal, |v| intravisit::walk_item(v, i)); } + fn visit_impl_item(&mut self, i: &hir::ImplItem) { + self.with_context(Normal, |v| intravisit::walk_impl_item(v, i)); + } + fn visit_expr(&mut self, e: &hir::Expr) { match e.node { hir::ExprWhile(ref e, ref b, _) => { diff --git a/src/librustc_plugin/build.rs b/src/librustc_plugin/build.rs index 0464a93ef717..75046f6aeb87 100644 --- a/src/librustc_plugin/build.rs +++ b/src/librustc_plugin/build.rs @@ -32,6 +32,9 @@ impl<'v> ItemLikeVisitor<'v> for RegistrarFinder { } } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } /// Find the function marked with `#[plugin_registrar]`, if any. diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index d9c1cfd9fdba..3fd1ed935165 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -124,6 +124,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { self.visit_item(tcx.map.expect_item(item.id)) } + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + let impl_item = self.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) + } + fn visit_item(&mut self, item: &hir::Item) { let inherited_item_level = match item.node { // Impls inherit level from their types and traits @@ -159,15 +164,17 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { } } } - hir::ItemImpl(.., None, _, ref impl_items) => { - for impl_item in impl_items { + hir::ItemImpl(.., None, _, ref impl_item_ids) => { + for &impl_item_id in impl_item_ids { + let impl_item = self.tcx.map.impl_item(impl_item_id); if impl_item.vis == hir::Public { self.update(impl_item.id, item_level); } } } - hir::ItemImpl(.., Some(_), _, ref impl_items) => { - for impl_item in impl_items { + hir::ItemImpl(.., Some(_), _, ref impl_item_ids) => { + for &impl_item_id in impl_item_ids { + let impl_item = self.tcx.map.impl_item(impl_item_id); self.update(impl_item.id, item_level); } } @@ -250,11 +257,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // The interface is empty hir::ItemDefaultImpl(..) => {} // Visit everything except for private impl items - hir::ItemImpl(.., ref generics, None, _, ref impl_items) => { + hir::ItemImpl(.., ref generics, None, _, ref impl_item_ids) => { if item_level.is_some() { self.reach().visit_generics(generics); - for impl_item in impl_items { - if self.get(impl_item.id).is_some() { + for &impl_item_id in impl_item_ids { + if self.get(impl_item_id.id).is_some() { + let impl_item = self.tcx.map.impl_item(impl_item_id); self.reach().visit_impl_item(impl_item); } } @@ -319,6 +327,12 @@ impl<'b, 'a, 'tcx: 'a> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + // when we visit an impl, its methods and items are part of its "interface" + let impl_item = self.ev.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) + } + fn visit_ty(&mut self, ty: &hir::Ty) { if let hir::TyPath(_, ref path) = ty.node { let def = self.ev.tcx.expect_def(ty.id); @@ -421,6 +435,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { self.visit_item(tcx.map.expect_item(item.id)) } + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + let impl_item = self.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) + } + fn visit_item(&mut self, item: &hir::Item) { let orig_curitem = replace(&mut self.curitem, item.id); intravisit::walk_item(self, item); @@ -625,6 +644,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> self.visit_item(tcx.map.expect_item(item.id)) } + fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) { + let impl_item = self.tcx.map.impl_item(item_id); + self.visit_impl_item(impl_item) + } + fn visit_item(&mut self, item: &hir::Item) { match item.node { // contents of a private mod can be reexported, so we need @@ -650,7 +674,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> // (i.e. we could just return here to not check them at // all, or some worse estimation of whether an impl is // publicly visible). - hir::ItemImpl(.., ref g, ref trait_ref, ref self_, ref impl_items) => { + hir::ItemImpl(.., ref g, ref trait_ref, ref self_, ref impl_item_ids) => { // `impl [... for] Private` is never visible. let self_contains_private; // impl [... for] Public<...>, but not `impl [... for] @@ -695,16 +719,17 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> // are private (because `T` won't be visible externally). let trait_or_some_public_method = trait_ref.is_some() || - impl_items.iter() - .any(|impl_item| { - match impl_item.node { - hir::ImplItemKind::Const(..) | - hir::ImplItemKind::Method(..) => { - self.access_levels.is_reachable(impl_item.id) - } - hir::ImplItemKind::Type(_) => false, - } - }); + impl_item_ids.iter() + .any(|&impl_item_id| { + let impl_item = self.tcx.map.impl_item(impl_item_id); + match impl_item.node { + hir::ImplItemKind::Const(..) | + hir::ImplItemKind::Method(..) => { + self.access_levels.is_reachable(impl_item.id) + } + hir::ImplItemKind::Type(_) => false, + } + }); if !self_contains_private && not_private_trait && @@ -714,12 +739,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> match *trait_ref { None => { - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { // This is where we choose whether to walk down // further into the impl to check its items. We // should only walk into public items so that we // don't erroneously report errors for private // types in private items. + let impl_item = self.tcx.map.impl_item(impl_item_id); match impl_item.node { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) @@ -751,7 +777,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> intravisit::walk_path(self, &tr.path); // Those in 3. are warned with this call. - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = self.tcx.map.impl_item(impl_item_id); if let hir::ImplItemKind::Type(ref ty) = impl_item.node { self.visit_ty(ty); } @@ -762,7 +789,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> // impl Public { ... }. Any public static // methods will be visible as `Public::foo`. let mut found_pub_static = false; - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = self.tcx.map.impl_item(impl_item_id); match impl_item.node { hir::ImplItemKind::Const(..) => { if self.item_is_public(&impl_item.id, &impl_item.vis) { @@ -1086,12 +1114,13 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for PrivateItemsInPublicInterfacesVisitor hir::ItemDefaultImpl(..) => {} // An inherent impl is public when its type is public // Subitems of inherent impls have their own publicity - hir::ItemImpl(.., ref generics, None, ref ty, ref impl_items) => { + hir::ItemImpl(.., ref generics, None, ref ty, ref impl_item_ids) => { let ty_vis = self.ty_visibility(ty); check.required_visibility = ty_vis; check.visit_generics(generics); - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = self.tcx.map.impl_item(impl_item_id); let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, self.tcx); check.required_visibility = min(impl_item_vis, ty_vis); @@ -1100,16 +1129,21 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for PrivateItemsInPublicInterfacesVisitor } // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity - hir::ItemImpl(.., ref generics, Some(ref trait_ref), ref ty, ref impl_items) => { + hir::ItemImpl(.., ref generics, Some(ref trait_ref), ref ty, ref impl_item_ids) => { let vis = min(self.ty_visibility(ty), self.trait_ref_visibility(trait_ref)); check.required_visibility = vis; check.visit_generics(generics); - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = self.tcx.map.impl_item(impl_item_id); check.visit_impl_item(impl_item); } } } } + + fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { + // handled in `visit_item` above + } } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d744d2a6db37..8245b0cf7f53 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -189,7 +189,7 @@ //! regardless of whether it is actually needed or not. use rustc::hir; -use rustc::hir::intravisit::{self, Visitor}; +use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; @@ -308,7 +308,7 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, output: &mut roots, }; - scx.tcx().map.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); + scx.tcx().map.krate().visit_all_item_likes(&mut visitor); } roots @@ -1031,7 +1031,7 @@ struct RootCollector<'b, 'a: 'b, 'tcx: 'a + 'b> { output: &'b mut Vec>, } -impl<'b, 'a, 'v> Visitor<'v> for RootCollector<'b, 'a, 'v> { +impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { fn visit_item(&mut self, item: &'v hir::Item) { match item.node { hir::ItemExternCrate(..) | @@ -1089,8 +1089,6 @@ impl<'b, 'a, 'v> Visitor<'v> for RootCollector<'b, 'a, 'v> { } } } - - intravisit::walk_item(self, item) } fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) { @@ -1125,8 +1123,6 @@ impl<'b, 'a, 'v> Visitor<'v> for RootCollector<'b, 'a, 'v> { } _ => { /* Nothing to do here */ } } - - intravisit::walk_impl_item(self, ii) } } @@ -1151,9 +1147,11 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, ' if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { let callee_substs = tcx.erase_regions(&trait_ref.substs); - let overridden_methods: FxHashSet<_> = items.iter() - .map(|item| item.name) - .collect(); + let overridden_methods: FxHashSet<_> = + items.iter() + .map(|&id| tcx.map.impl_item(id)) + .map(|item| item.name) + .collect(); for method in tcx.provided_trait_methods(trait_ref.def_id) { if overridden_methods.contains(&method.name) { continue; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 35f419bbf739..6093e45e5a21 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -460,6 +460,9 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { _ => {} } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } ccx.tcx.map.krate().visit_all_item_likes(&mut Visitor { map: &ccx.tcx.map, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7cf773688e6d..e8ebc2eee63d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -530,6 +530,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemBodiesVisitor<'a, 'tcx> { fn visit_item(&mut self, i: &'tcx hir::Item) { check_item_body(self.ccx, i); } + + fn visit_impl_item(&mut self, _item: &'tcx hir::ImplItem) { + // done as part of `visit_item` above + } } pub fn check_wf_new(ccx: &CrateCtxt) -> CompileResult { @@ -811,7 +815,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { it.id); } hir::ItemFn(..) => {} // entirely within check_item_body - hir::ItemImpl(.., ref impl_items) => { + hir::ItemImpl(.., ref impl_item_ids) => { debug!("ItemImpl {} with id {}", it.name, it.id); let impl_def_id = ccx.tcx.map.local_def_id(it.id); if let Some(impl_trait_ref) = ccx.tcx.impl_trait_ref(impl_def_id) { @@ -819,7 +823,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { it.span, impl_def_id, impl_trait_ref, - impl_items); + impl_item_ids); let trait_def_id = impl_trait_ref.def_id; check_on_unimplemented(ccx, trait_def_id, it); } @@ -881,10 +885,11 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { hir::ItemFn(ref decl, .., ref body) => { check_bare_fn(ccx, &decl, &body, it.id, it.span); } - hir::ItemImpl(.., ref impl_items) => { + hir::ItemImpl(.., ref impl_item_ids) => { debug!("ItemImpl {} with id {}", it.name, it.id); - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = ccx.tcx.map.impl_item(impl_item_id); match impl_item.node { hir::ImplItemKind::Const(_, ref expr) => { check_const(ccx, &expr, impl_item.id) @@ -1021,7 +1026,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_span: Span, impl_id: DefId, impl_trait_ref: ty::TraitRef<'tcx>, - impl_items: &[hir::ImplItem]) { + impl_item_ids: &[hir::ImplItemId]) { // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` // isn't populated for such impls. @@ -1032,9 +1037,11 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id); let mut overridden_associated_type = None; + let impl_items = || impl_item_ids.iter().map(|&id| ccx.tcx.map.impl_item(id)); + // Check existing impl methods to see if they are both present in trait // and compatible with trait signature - for impl_item in impl_items { + for impl_item in impl_items() { let ty_impl_item = tcx.associated_item(tcx.map.local_def_id(impl_item.id)); let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id) .find(|ac| ac.name == ty_impl_item.name); diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index d9411070e2e8..b4a10c52270e 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -58,6 +58,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> { } } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index e8b0044ed20c..31bd7b0f19b3 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -57,6 +57,9 @@ impl<'a, 'gcx, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCheckVisitor<'a, 'gcx, self.cc.check_implementation(item) } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index d5a7726aa142..a507077bef77 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -384,4 +384,8 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { self.check_item(item); } + + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index fb17255ccbc6..c66a76ebba02 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -199,4 +199,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { _ => {} } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index dd9d3e0d5b7e..6d5de8f25065 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -106,4 +106,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> { _ => {} } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 52669ccc8425..658a655c2dec 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -149,6 +149,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> { } intravisit::walk_ty(self, ty); } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + // handled in `visit_item` above; we may want to break this out later + } } /////////////////////////////////////////////////////////////////////////// @@ -727,7 +731,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { ref generics, ref opt_trait_ref, ref selfty, - ref impl_items) => { + ref impl_item_ids) => { // Create generics from the generics specified in the impl head. debug!("convert: ast_generics={:?}", generics); let def_id = ccx.tcx.map.local_def_id(it.id); @@ -757,7 +761,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let mut seen_type_items = FxHashMap(); let mut seen_value_items = FxHashMap(); - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = tcx.map.impl_item(impl_item_id); let seen_items = match impl_item.node { hir::ImplItemKind::Type(_) => &mut seen_type_items, _ => &mut seen_value_items, @@ -790,7 +795,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } // Convert all the associated types. - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = tcx.map.impl_item(impl_item_id); if let hir::ImplItemKind::Type(ref ty) = impl_item.node { let type_def_id = ccx.tcx.map.local_def_id(impl_item.id); generics_of_def_id(ccx, type_def_id); @@ -806,7 +812,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } - for impl_item in impl_items { + for &impl_item_id in impl_item_ids { + let impl_item = tcx.map.impl_item(impl_item_id); if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { convert_method(ccx, ImplContainer(def_id), impl_item.id, sig, selfty, @@ -814,7 +821,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } - enforce_impl_lifetimes_are_constrained(ccx, generics, def_id, impl_items); + enforce_impl_lifetimes_are_constrained(ccx, generics, def_id, impl_item_ids); }, hir::ItemTrait(.., ref trait_items) => { let trait_def = trait_def_of_item(ccx, it); @@ -2103,7 +2110,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ast_generics: &hir::Generics, impl_def_id: DefId, - impl_items: &[hir::ImplItem]) + impl_item_ids: &[hir::ImplItemId]) { // Every lifetime used in an associated type must be constrained. let impl_ty = ccx.tcx.item_type(impl_def_id); @@ -2118,8 +2125,8 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ctp::identify_constrained_type_params( &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); - let lifetimes_in_associated_types: FxHashSet<_> = impl_items.iter() - .map(|item| ccx.tcx.map.local_def_id(item.id)) + let lifetimes_in_associated_types: FxHashSet<_> = impl_item_ids.iter() + .map(|item_id| ccx.tcx.map.local_def_id(item_id.id)) .filter(|&def_id| { let item = ccx.tcx.associated_item(def_id); item.kind == ty::AssociatedKind::Type && item.has_value diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 2c045bc88a26..8a0c1c68322d 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -115,6 +115,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { hir::ItemDefaultImpl(..) => {} } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } /// Is `param_id` a lifetime according to `map`? diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index c40adb5f428e..0a3238480d90 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -257,4 +257,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { hir::ItemTy(..) => {} } } + + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) { + } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index d9155e10e17b..6587392e18ff 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -502,10 +502,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.traits.push(t); }, - hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref items) => { + hir::ItemImpl(unsafety, polarity, ref gen, ref tr, ref ty, ref item_ids) => { // Don't duplicate impls when inlining, we'll pick them up // regardless of where they're located. if !self.inlining { + let items = item_ids.iter() + .map(|&id| self.cx.map.impl_item(id).clone()) + .collect(); let i = Impl { unsafety: unsafety, polarity: polarity,