about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/itemlikevisit.rs5
-rw-r--r--src/librustc/hir/map/collector.rs4
-rw-r--r--src/librustc/lint/context.rs9
-rw-r--r--src/librustc/middle/dead.rs30
-rw-r--r--src/librustc/middle/entry.rs6
-rw-r--r--src/librustc/middle/lang_items.rs4
-rw-r--r--src/librustc/middle/reachable.rs4
-rw-r--r--src/librustc/middle/resolve_lifetime.rs5
-rw-r--r--src/librustc/middle/stability.rs23
-rw-r--r--src/librustc_driver/derive_registrar.rs4
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs4
-rw-r--r--src/librustc_incremental/calculate_svh/svh_visitor.rs6
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs6
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs8
-rw-r--r--src/librustc_passes/loops.rs4
-rw-r--r--src/librustc_plugin/build.rs3
-rw-r--r--src/librustc_privacy/lib.rs84
-rw-r--r--src/librustc_trans/collector.rs18
-rw-r--r--src/librustc_typeck/check/method/suggest.rs3
-rw-r--r--src/librustc_typeck/check/mod.rs19
-rw-r--r--src/librustc_typeck/check_unused.rs3
-rw-r--r--src/librustc_typeck/coherence/mod.rs3
-rw-r--r--src/librustc_typeck/coherence/orphan.rs4
-rw-r--r--src/librustc_typeck/coherence/overlap.rs3
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs3
-rw-r--r--src/librustc_typeck/collect.rs23
-rw-r--r--src/librustc_typeck/variance/constraints.rs3
-rw-r--r--src/librustc_typeck/variance/terms.rs3
-rw-r--r--src/librustdoc/visit_ast.rs5
30 files changed, 233 insertions, 70 deletions
diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs
index 22b56604428..1e373441e9e 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 04fcf7e8450..eafb7949da3 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 50c58105740..78049663afe 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 2667943bea9..57abf0bdc42 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<ast::NodeId>
+struct LifeSeeder<'k> {
+    worklist: Vec<ast::NodeId>,
+    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 e5112749c0e..9dd54457a34 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 6fe8442474a..9b4b1396669 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 848f4218d88..0a45f895d7d 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 c342342d73b..68d2cceda84 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 d79833998d6..f8d58c5f2d9 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 605193a0434..4db620b2bec 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 84489c2e8c6..d66e0f6aba3 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 0b0dd596784..3060e237fc1 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 f6b7abd2ef1..0cd1c88fb87 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 bbffe88316b..2d96eeb8f20 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 b33a7060e37..21bebb2562a 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 adcb7842ee1..724100e0223 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 0464a93ef71..75046f6aeb8 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 d9c1cfd9fdb..3fd1ed93516 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<Private> { ... }. 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 d744d2a6db3..8245b0cf7f5 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<TransItem<'tcx>>,
 }
 
-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 35f419bbf73..6093e45e5a2 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 7cf773688e6..e8ebc2eee63 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 d9411070e2e..b4a10c52270 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 e8b0044ed20..31bd7b0f19b 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 d5a7726aa14..a507077bef7 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 fb17255ccbc..c66a76ebba0 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 dd9d3e0d5b7..6d5de8f2506 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 52669ccc842..658a655c2de 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 2c045bc88a2..8a0c1c68322 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 c40adb5f428..0a3238480d9 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 d9155e10e17..6587392e18f 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,