about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2016-12-04 04:21:06 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2016-12-28 11:21:45 +0200
commit864928297d0fc0675c5eae62a58d8488941d58cf (patch)
tree1ea528de95d704bc8ebfde9af807287477d5d3d9 /src/librustc
parent6ebb6fdbee7f0d250e50e4d84d9aede293cf3bb3 (diff)
downloadrust-864928297d0fc0675c5eae62a58d8488941d58cf.tar.gz
rust-864928297d0fc0675c5eae62a58d8488941d58cf.zip
rustc: separate TraitItem from their parent Item, just like ImplItem.
Diffstat (limited to 'src/librustc')
-rw-r--r--src/librustc/dep_graph/visit.rs11
-rw-r--r--src/librustc/hir/intravisit.rs39
-rw-r--r--src/librustc/hir/itemlikevisit.rs7
-rw-r--r--src/librustc/hir/lowering.rs53
-rw-r--r--src/librustc/hir/map/blocks.rs4
-rw-r--r--src/librustc/hir/map/collector.rs4
-rw-r--r--src/librustc/hir/map/mod.rs51
-rw-r--r--src/librustc/hir/mod.rs63
-rw-r--r--src/librustc/hir/print.rs18
-rw-r--r--src/librustc/infer/error_reporting.rs2
-rw-r--r--src/librustc/middle/cstore.rs4
-rw-r--r--src/librustc/middle/dead.rs23
-rw-r--r--src/librustc/middle/entry.rs5
-rw-r--r--src/librustc/middle/intrinsicck.rs2
-rw-r--r--src/librustc/middle/lang_items.rs4
-rw-r--r--src/librustc/middle/reachable.rs18
-rw-r--r--src/librustc/middle/resolve_lifetime.rs2
-rw-r--r--src/librustc/mir/transform.rs2
-rw-r--r--src/librustc/ty/mod.rs46
19 files changed, 240 insertions, 118 deletions
diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs
index f6a22e47cf2..61f58fc8fe5 100644
--- a/src/librustc/dep_graph/visit.rs
+++ b/src/librustc/dep_graph/visit.rs
@@ -45,6 +45,17 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>
             debug!("Ended task {:?}", task_id);
         }
 
+        fn visit_trait_item(&mut self, i: &'tcx hir::TraitItem) {
+            let trait_item_def_id = self.tcx.map.local_def_id(i.id);
+            let task_id = (self.dep_node_fn)(trait_item_def_id);
+            let _task = self.tcx.dep_graph.in_task(task_id.clone());
+            debug!("Started task {:?}", task_id);
+            assert!(!self.tcx.map.is_inlined_def_id(trait_item_def_id));
+            self.tcx.dep_graph.read(DepNode::Hir(trait_item_def_id));
+            self.visitor.visit_trait_item(i);
+            debug!("Ended task {:?}", task_id);
+        }
+
         fn visit_impl_item(&mut self, i: &'tcx hir::ImplItem) {
             let impl_item_def_id = self.tcx.map.local_def_id(i.id);
             let task_id = (self.dep_node_fn)(impl_item_def_id);
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 474d7d508c4..e16c97f2d25 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -177,6 +177,17 @@ pub trait Visitor<'v> : Sized {
         }
     }
 
+    /// Like `visit_nested_item()`, but for trait items. See
+    /// `visit_nested_item()` for advice on when to override this
+    /// method.
+    #[allow(unused_variables)]
+    fn visit_nested_trait_item(&mut self, id: TraitItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id));
+        if let Some(item) = opt_item {
+            self.visit_trait_item(item);
+        }
+    }
+
     /// Like `visit_nested_item()`, but for impl items. See
     /// `visit_nested_item()` for advice on when to override this
     /// method.
@@ -273,6 +284,9 @@ pub trait Visitor<'v> : Sized {
     fn visit_trait_item(&mut self, ti: &'v TraitItem) {
         walk_trait_item(self, ti)
     }
+    fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
+        walk_trait_item_ref(self, ii)
+    }
     fn visit_impl_item(&mut self, ii: &'v ImplItem) {
         walk_impl_item(self, ii)
     }
@@ -469,9 +483,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_list!(visitor, visit_trait_ref, opt_trait_reference);
             visitor.visit_ty(typ);
-            for impl_item_ref in impl_item_refs {
-                visitor.visit_impl_item_ref(impl_item_ref);
-            }
+            walk_list!(visitor, visit_impl_item_ref, impl_item_refs);
         }
         ItemStruct(ref struct_definition, ref generics) |
         ItemUnion(ref struct_definition, ref generics) => {
@@ -479,11 +491,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
         }
-        ItemTrait(_, ref generics, ref bounds, ref methods) => {
+        ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => {
             visitor.visit_id(item.id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
-            walk_list!(visitor, visit_trait_item, methods);
+            walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
         }
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
@@ -788,17 +800,17 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
     visitor.visit_name(trait_item.span, trait_item.name);
     walk_list!(visitor, visit_attribute, &trait_item.attrs);
     match trait_item.node {
-        ConstTraitItem(ref ty, ref default) => {
+        TraitItemKind::Const(ref ty, ref default) => {
             visitor.visit_id(trait_item.id);
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, default);
         }
-        MethodTraitItem(ref sig, None) => {
+        TraitItemKind::Method(ref sig, None) => {
             visitor.visit_id(trait_item.id);
             visitor.visit_generics(&sig.generics);
             visitor.visit_fn_decl(&sig.decl);
         }
-        MethodTraitItem(ref sig, Some(body_id)) => {
+        TraitItemKind::Method(ref sig, Some(body_id)) => {
             visitor.visit_fn(FnKind::Method(trait_item.name,
                                             sig,
                                             None,
@@ -808,7 +820,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
                              trait_item.span,
                              trait_item.id);
         }
-        TypeTraitItem(ref bounds, ref default) => {
+        TraitItemKind::Type(ref bounds, ref default) => {
             visitor.visit_id(trait_item.id);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_ty, default);
@@ -816,6 +828,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
     }
 }
 
+pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) {
+    // NB: Deliberately force a compilation error if/when new fields are added.
+    let TraitItemRef { id, name, ref kind, span, ref defaultness } = *trait_item_ref;
+    visitor.visit_nested_trait_item(id);
+    visitor.visit_name(span, name);
+    visitor.visit_associated_item_kind(kind);
+    visitor.visit_defaultness(defaultness);
+}
+
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
     // NB: Deliberately force a compilation error if/when new fields are added.
     let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item;
diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs
index 71ef7131440..f359ca20163 100644
--- a/src/librustc/hir/itemlikevisit.rs
+++ b/src/librustc/hir/itemlikevisit.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{Item, ImplItem};
+use super::{Item, ImplItem, TraitItem};
 use super::intravisit::Visitor;
 
 /// The "item-like visitor" visitor defines only the top-level methods
@@ -58,6 +58,7 @@ use super::intravisit::Visitor;
 /// needed.
 pub trait ItemLikeVisitor<'hir> {
     fn visit_item(&mut self, item: &'hir Item);
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem);
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem);
 }
 
@@ -80,6 +81,10 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
         self.visitor.visit_item(item);
     }
 
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem) {
+        self.visitor.visit_trait_item(trait_item);
+    }
+
     fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) {
         self.visitor.visit_impl_item(impl_item);
     }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index d1fe19364b4..75228811813 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -51,7 +51,6 @@ use rustc_data_structures::fnv::FnvHashMap;
 
 use std::collections::BTreeMap;
 use std::iter;
-use std::mem;
 
 use syntax::ast::*;
 use syntax::errors;
@@ -77,6 +76,7 @@ pub struct LoweringContext<'a> {
     /// The items being lowered are collected here.
     items: BTreeMap<NodeId, hir::Item>,
 
+    trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
 }
 
@@ -108,6 +108,7 @@ pub fn lower_crate(sess: &Session,
         exprs: FnvHashMap(),
         resolver: resolver,
         items: BTreeMap::new(),
+        trait_items: BTreeMap::new(),
         impl_items: BTreeMap::new(),
     }.lower_crate(krate)
 }
@@ -133,8 +134,9 @@ impl<'a> LoweringContext<'a> {
             span: c.span,
             exported_macros: exported_macros,
             items: self.items,
+            trait_items: self.trait_items,
             impl_items: self.impl_items,
-            exprs: mem::replace(&mut self.exprs, FnvHashMap()),
+            exprs: self.exprs,
         }
     }
 
@@ -150,8 +152,15 @@ impl<'a> LoweringContext<'a> {
                 visit::walk_item(self, item);
             }
 
+            fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
+                let id = hir::TraitItemId { node_id: item.id };
+                let hir_item = self.lctx.lower_trait_item(item);
+                self.lctx.trait_items.insert(id, hir_item);
+                visit::walk_trait_item(self, item);
+            }
+
             fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
-                let id = self.lctx.lower_impl_item_ref(item).id;
+                let id = hir::ImplItemId { node_id: item.id };
                 let hir_item = self.lctx.lower_impl_item(item);
                 self.lctx.impl_items.insert(id, hir_item);
                 visit::walk_impl_item(self, item);
@@ -907,7 +916,7 @@ impl<'a> LoweringContext<'a> {
             }
             ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_bounds(bounds);
-                let items = items.iter().map(|item| self.lower_trait_item(item)).collect();
+                let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
                 hir::ItemTrait(self.lower_unsafety(unsafety),
                                self.lower_generics(generics),
                                bounds,
@@ -925,20 +934,20 @@ impl<'a> LoweringContext<'a> {
                 attrs: this.lower_attrs(&i.attrs),
                 node: match i.node {
                     TraitItemKind::Const(ref ty, ref default) => {
-                        hir::ConstTraitItem(this.lower_ty(ty),
-                                            default.as_ref().map(|x| P(this.lower_expr(x))))
+                        hir::TraitItemKind::Const(this.lower_ty(ty),
+                                                  default.as_ref().map(|x| P(this.lower_expr(x))))
                     }
                     TraitItemKind::Method(ref sig, ref body) => {
-                        hir::MethodTraitItem(this.lower_method_sig(sig),
-                                             body.as_ref().map(|x| {
+                        hir::TraitItemKind::Method(this.lower_method_sig(sig),
+                                                   body.as_ref().map(|x| {
                             let body = this.lower_block(x);
                             let expr = this.expr_block(body, ThinVec::new());
                             this.record_expr(expr)
                         }))
                     }
                     TraitItemKind::Type(ref bounds, ref default) => {
-                        hir::TypeTraitItem(this.lower_bounds(bounds),
-                                           default.as_ref().map(|x| this.lower_ty(x)))
+                        hir::TraitItemKind::Type(this.lower_bounds(bounds),
+                                                 default.as_ref().map(|x| this.lower_ty(x)))
                     }
                     TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
                 },
@@ -947,6 +956,30 @@ impl<'a> LoweringContext<'a> {
         })
     }
 
+    fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
+        let (kind, has_default) = match i.node {
+            TraitItemKind::Const(_, ref default) => {
+                (hir::AssociatedItemKind::Const, default.is_some())
+            }
+            TraitItemKind::Type(_, ref default) => {
+                (hir::AssociatedItemKind::Type, default.is_some())
+            }
+            TraitItemKind::Method(ref sig, ref default) => {
+                (hir::AssociatedItemKind::Method {
+                    has_self: sig.decl.has_self(),
+                 }, default.is_some())
+            }
+            TraitItemKind::Macro(..) => unimplemented!(),
+        };
+        hir::TraitItemRef {
+            id: hir::TraitItemId { node_id: i.id },
+            name: i.ident.name,
+            span: i.span,
+            defaultness: self.lower_defaultness(Defaultness::Default, has_default),
+            kind: kind,
+        }
+    }
+
     fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
         self.with_parent_def(i.id, |this| {
             hir::ImplItem {
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 068e7ed8624..8df4d669d0c 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -62,7 +62,7 @@ impl MaybeFnLike for ast::Item {
 
 impl MaybeFnLike for ast::TraitItem {
     fn is_fn_like(&self) -> bool {
-        match self.node { ast::MethodTraitItem(_, Some(_)) => true, _ => false, }
+        match self.node { ast::TraitItemKind::Method(_, Some(_)) => true, _ => false, }
     }
 }
 
@@ -252,7 +252,7 @@ impl<'a> FnLikeNode<'a> {
                 _ => bug!("item FnLikeNode that is not fn-like"),
             },
             map::NodeTraitItem(ti) => match ti.node {
-                ast::MethodTraitItem(ref sig, Some(body)) => {
+                ast::TraitItemKind::Method(ref sig, Some(body)) => {
                     method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs)
                 }
                 _ => bug!("trait method FnLikeNode that is not fn-like"),
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 45988886a60..9a4047f70e3 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -98,6 +98,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         }
     }
 
+    fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
+        self.visit_trait_item(self.krate.trait_item(item_id))
+    }
+
     fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
         self.visit_impl_item(self.krate.impl_item(item_id))
     }
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 4546f6d8c27..a6ead8efe51 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -257,10 +257,20 @@ impl<'ast> Map<'ast> {
 
                         if let Some(last_id) = last_expr {
                             // The body of the item may have a separate dep node
-                            // (Note that trait items don't currently have
-                            // their own dep node, so there's also just one
-                            // HirBody node for all the items)
-                            if self.is_body(last_id, item) {
+                            if self.is_item_body(last_id, item) {
+                                return DepNode::HirBody(def_id);
+                            }
+                        }
+                        return DepNode::Hir(def_id);
+                    }
+
+                    EntryTraitItem(_, item) => {
+                        let def_id = self.local_def_id(id);
+                        assert!(!self.is_inlined_def_id(def_id));
+
+                        if let Some(last_id) = last_expr {
+                            // The body of the item may have a separate dep node
+                            if self.is_trait_item_body(last_id, item) {
                                 return DepNode::HirBody(def_id);
                             }
                         }
@@ -280,7 +290,6 @@ impl<'ast> Map<'ast> {
                     }
 
                     EntryForeignItem(p, _) |
-                    EntryTraitItem(p, _) |
                     EntryVariant(p, _) |
                     EntryField(p, _) |
                     EntryStmt(p, _) |
@@ -358,18 +367,16 @@ impl<'ast> Map<'ast> {
         }
     }
 
-    fn is_body(&self, node_id: NodeId, item: &Item) -> bool {
+    fn is_item_body(&self, node_id: NodeId, item: &Item) -> bool {
         match item.node {
             ItemFn(_, _, _, _, _, body) => body.node_id() == node_id,
-            // Since trait items currently don't get their own dep nodes,
-            // we check here whether node_id is the body of any of the items.
-            // If they get their own dep nodes, this can go away
-            ItemTrait(_, _, _, ref trait_items) => {
-                trait_items.iter().any(|trait_item| { match trait_item.node {
-                    MethodTraitItem(_, Some(body)) => body.node_id() == node_id,
-                    _ => false
-                }})
-            }
+            _ => false
+        }
+    }
+
+    fn is_trait_item_body(&self, node_id: NodeId, item: &TraitItem) -> bool {
+        match item.node {
+            TraitItemKind::Method(_, Some(body)) => body.node_id() == node_id,
             _ => false
         }
     }
@@ -436,6 +443,14 @@ impl<'ast> Map<'ast> {
         self.forest.krate()
     }
 
+    pub fn trait_item(&self, id: TraitItemId) -> &'ast TraitItem {
+        self.read(id.node_id);
+
+        // NB: intentionally bypass `self.forest.krate()` so that we
+        // do not trigger a read of the whole krate here
+        self.forest.krate.trait_item(id)
+    }
+
     pub fn impl_item(&self, id: ImplItemId) -> &'ast ImplItem {
         self.read(id.node_id);
 
@@ -1045,9 +1060,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         }
         Some(NodeTraitItem(ti)) => {
             let kind = match ti.node {
-                ConstTraitItem(..) => "assoc constant",
-                MethodTraitItem(..) => "trait method",
-                TypeTraitItem(..) => "assoc type",
+                TraitItemKind::Const(..) => "assoc constant",
+                TraitItemKind::Method(..) => "trait method",
+                TraitItemKind::Type(..) => "assoc type",
             };
 
             format!("{} {} in {}{}", kind, ti.name, path_str(), id_str)
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index d135762ae82..db65d34e3d9 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -22,7 +22,6 @@ pub use self::Item_::*;
 pub use self::Mutability::*;
 pub use self::PrimTy::*;
 pub use self::Stmt_::*;
-pub use self::TraitItem_::*;
 pub use self::Ty_::*;
 pub use self::TyParamBound::*;
 pub use self::UnOp::*;
@@ -41,7 +40,7 @@ use syntax::abi::Abi;
 use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
 use syntax::ptr::P;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::Symbol;
 use syntax::tokenstream::TokenTree;
 use syntax::util::ThinVec;
 
@@ -431,6 +430,7 @@ pub struct Crate {
     // slightly different results.
     pub items: BTreeMap<NodeId, Item>,
 
+    pub trait_items: BTreeMap<TraitItemId, TraitItem>,
     pub impl_items: BTreeMap<ImplItemId, ImplItem>,
     pub exprs: FnvHashMap<ExprId, Expr>,
 }
@@ -440,6 +440,10 @@ impl Crate {
         &self.items[&id]
     }
 
+    pub fn trait_item(&self, id: TraitItemId) -> &TraitItem {
+        &self.trait_items[&id]
+    }
+
     pub fn impl_item(&self, id: ImplItemId) -> &ImplItem {
         &self.impl_items[&id]
     }
@@ -459,6 +463,10 @@ impl Crate {
             visitor.visit_item(item);
         }
 
+        for (_, trait_item) in &self.trait_items {
+            visitor.visit_trait_item(trait_item);
+        }
+
         for (_, impl_item) in &self.impl_items {
             visitor.visit_impl_item(impl_item);
         }
@@ -1070,6 +1078,14 @@ pub struct MethodSig {
     pub generics: Generics,
 }
 
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitItemId {
+    pub node_id: NodeId,
+}
+
 /// Represents an item declaration within a trait declaration,
 /// possibly including a default implementation. A trait item is
 /// either required (meaning it doesn't have an implementation, just a
@@ -1079,21 +1095,21 @@ pub struct TraitItem {
     pub id: NodeId,
     pub name: Name,
     pub attrs: HirVec<Attribute>,
-    pub node: TraitItem_,
+    pub node: TraitItemKind,
     pub span: Span,
 }
 
 /// Represents a trait method or associated constant or type
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TraitItem_ {
+pub enum TraitItemKind {
     /// An associated constant with an optional value (otherwise `impl`s
     /// must contain a value)
-    ConstTraitItem(P<Ty>, Option<P<Expr>>),
+    Const(P<Ty>, Option<P<Expr>>),
     /// A method with an optional body
-    MethodTraitItem(MethodSig, Option<ExprId>),
+    Method(MethodSig, Option<ExprId>),
     /// An associated type with (possibly empty) bounds and optional concrete
     /// type
-    TypeTraitItem(TyParamBounds, Option<P<Ty>>),
+    Type(TyParamBounds, Option<P<Ty>>),
 }
 
 // The bodies for items are stored "out of line", in a separate
@@ -1234,16 +1250,6 @@ pub struct Arg {
     pub id: NodeId,
 }
 
-impl Arg {
-    fn is_self(&self) -> bool {
-        if let PatKind::Binding(_, _, name, _) = self.pat.node {
-            name.node == keywords::SelfValue.name()
-        } else {
-            false
-        }
-    }
-}
-
 /// Represents the header (not the body) of a function declaration
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct FnDecl {
@@ -1252,12 +1258,6 @@ pub struct FnDecl {
     pub variadic: bool,
 }
 
-impl FnDecl {
-    pub fn has_self(&self) -> bool {
-        self.inputs.get(0).map(Arg::is_self).unwrap_or(false)
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
@@ -1548,7 +1548,7 @@ pub enum Item_ {
     /// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
     ItemUnion(VariantData, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItem>),
+    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
 
     // Default trait implementations
     ///
@@ -1584,6 +1584,21 @@ impl Item_ {
     }
 }
 
+/// A reference from an trait to one of its associated items. This
+/// contains the item's id, naturally, but also the item's name and
+/// some other high-level details (like whether it is an associated
+/// type or method, and whether it is public). This allows other
+/// passes to find the impl they want without loading the id (which
+/// means fewer edges in the incremental compilation graph).
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct TraitItemRef {
+    pub id: TraitItemId,
+    pub name: Name,
+    pub kind: AssociatedItemKind,
+    pub span: Span,
+    pub defaultness: Defaultness,
+}
+
 /// A reference from an impl to one of its associated items. This
 /// contains the item's id, naturally, but also the item's name and
 /// some other high-level details (like whether it is an associated
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index eaed62e4dce..745ab4e6372 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -858,7 +858,7 @@ impl<'a> State<'a> {
                 word(&mut self.s, " ")?;
                 self.bopen()?;
                 for trait_item in trait_items {
-                    self.print_trait_item(trait_item)?;
+                    self.print_trait_item_ref(trait_item)?;
                 }
                 self.bclose(item.span)?;
             }
@@ -1008,19 +1008,29 @@ impl<'a> State<'a> {
                       vis)
     }
 
+    pub fn print_trait_item_ref(&mut self, item_ref: &hir::TraitItemRef) -> io::Result<()> {
+        if let Some(krate) = self.krate {
+            // skip nested items if krate context was not provided
+            let item = &krate.trait_item(item_ref.id);
+            self.print_trait_item(item)
+        } else {
+            Ok(())
+        }
+    }
+
     pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
         self.ann.pre(self, NodeSubItem(ti.id))?;
         self.hardbreak_if_not_bol()?;
         self.maybe_print_comment(ti.span.lo)?;
         self.print_outer_attributes(&ti.attrs)?;
         match ti.node {
-            hir::ConstTraitItem(ref ty, ref default) => {
+            hir::TraitItemKind::Const(ref ty, ref default) => {
                 self.print_associated_const(ti.name,
                                             &ty,
                                             default.as_ref().map(|expr| &**expr),
                                             &hir::Inherited)?;
             }
-            hir::MethodTraitItem(ref sig, ref body) => {
+            hir::TraitItemKind::Method(ref sig, ref body) => {
                 if body.is_some() {
                     self.head("")?;
                 }
@@ -1034,7 +1044,7 @@ impl<'a> State<'a> {
                     word(&mut self.s, ";")?;
                 }
             }
-            hir::TypeTraitItem(ref bounds, ref default) => {
+            hir::TraitItemKind::Type(ref bounds, ref default) => {
                 self.print_associated_type(ti.name,
                                            Some(bounds),
                                            default.as_ref().map(|ty| &**ty))?;
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 9d48fbca53e..026f4b187e2 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -1079,7 +1079,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 },
                 ast_map::NodeTraitItem(item) => {
                     match item.node {
-                        hir::MethodTraitItem(ref sig, Some(_)) => {
+                        hir::TraitItemKind::Method(ref sig, Some(_)) => {
                             Some((&sig.decl,
                                   &sig.generics,
                                   sig.unsafety,
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index d0003693eef..7d570596386 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -183,9 +183,9 @@ impl<'a> InlinedItemRef<'a> {
                            _tcx: TyCtxt)
                            -> InlinedItemRef<'a> {
         let (body, args) = match item.node {
-            hir::ConstTraitItem(_, Some(ref body)) =>
+            hir::TraitItemKind::Const(_, Some(ref body)) =>
                 (&**body, Vec::new()),
-            hir::ConstTraitItem(_, None) => {
+            hir::TraitItemKind::Const(_, None) => {
                 bug!("InlinedItemRef::from_trait_item called for const without body")
             },
             _ => bug!("InlinedItemRef::from_trait_item wrong kind")
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 1c5dd97b74b..2206336164a 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -328,11 +328,12 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> {
                 self.worklist.extend(enum_def.variants.iter()
                                                       .map(|variant| variant.node.data.id()));
             }
-            hir::ItemTrait(.., ref trait_items) => {
-                for trait_item in trait_items {
+            hir::ItemTrait(.., ref trait_item_refs) => {
+                for trait_item_ref in trait_item_refs {
+                    let trait_item = self.krate.trait_item(trait_item_ref.id);
                     match trait_item.node {
-                        hir::ConstTraitItem(_, Some(_)) |
-                        hir::MethodTraitItem(_, Some(_)) => {
+                        hir::TraitItemKind::Const(_, Some(_)) |
+                        hir::TraitItemKind::Method(_, Some(_)) => {
                             if has_allow_dead_code_or_lang_attr(&trait_item.attrs) {
                                 self.worklist.push(trait_item.id);
                             }
@@ -354,6 +355,10 @@ impl<'v, 'k> ItemLikeVisitor<'v> for LifeSeeder<'k> {
         }
     }
 
+    fn visit_trait_item(&mut self, _item: &hir::TraitItem) {
+        // ignore: we are handling this in `visit_item` above
+    }
+
     fn visit_impl_item(&mut self, _item: &hir::ImplItem) {
         // ignore: we are handling this in `visit_item` above
     }
@@ -567,15 +572,15 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
     // Overwrite so that we don't warn the trait item itself.
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
         match trait_item.node {
-            hir::ConstTraitItem(_, Some(ref body)) => {
+            hir::TraitItemKind::Const(_, Some(ref body)) => {
                 intravisit::walk_expr(self, body)
             }
-            hir::MethodTraitItem(_, Some(body_id)) => {
+            hir::TraitItemKind::Method(_, Some(body_id)) => {
                 self.visit_body(body_id)
             }
-            hir::ConstTraitItem(_, None) |
-            hir::MethodTraitItem(_, None) |
-            hir::TypeTraitItem(..) => {}
+            hir::TraitItemKind::Const(_, None) |
+            hir::TraitItemKind::Method(_, None) |
+            hir::TraitItemKind::Type(..) => {}
         }
     }
 }
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index e927843a984..f2e46d4cbc9 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, ImplItem};
+use hir::{Item, ItemFn, ImplItem, TraitItem};
 use hir::itemlikevisit::ItemLikeVisitor;
 
 struct EntryContext<'a, 'tcx: 'a> {
@@ -47,6 +47,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
         find_item(item, self, at_root);
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &'tcx TraitItem) {
+        // entry fn is never a trait item
+    }
 
     fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) {
         // entry fn is never an impl item
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 2357549c82e..1c31e1800ee 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -132,7 +132,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> {
     }
 
     fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
-        if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
+        if let hir::TraitItemKind::Const(_, Some(ref expr)) = item.node {
             self.visit_const(item.id, expr);
         } else {
             intravisit::walk_trait_item(self, item);
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 029a1d66add..4cae5b370eb 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -140,6 +140,10 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+        // at present, lang items are always items, not trait items
+    }
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
         // at present, lang items are always items, not impl items
     }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 2c4710f1e45..25f70d04819 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -166,9 +166,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             }
             Some(ast_map::NodeTraitItem(trait_method)) => {
                 match trait_method.node {
-                    hir::ConstTraitItem(_, ref default) => default.is_some(),
-                    hir::MethodTraitItem(_, ref body) => body.is_some(),
-                    hir::TypeTraitItem(..) => false,
+                    hir::TraitItemKind::Const(_, ref default) => default.is_some(),
+                    hir::TraitItemKind::Method(_, ref body) => body.is_some(),
+                    hir::TraitItemKind::Type(..) => false,
                 }
             }
             Some(ast_map::NodeImplItem(impl_item)) => {
@@ -274,17 +274,17 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             }
             ast_map::NodeTraitItem(trait_method) => {
                 match trait_method.node {
-                    hir::ConstTraitItem(_, None) |
-                    hir::MethodTraitItem(_, None) => {
+                    hir::TraitItemKind::Const(_, None) |
+                    hir::TraitItemKind::Method(_, None) => {
                         // Keep going, nothing to get exported
                     }
-                    hir::ConstTraitItem(_, Some(ref body)) => {
+                    hir::TraitItemKind::Const(_, Some(ref body)) => {
                         self.visit_expr(body);
                     }
-                    hir::MethodTraitItem(_, Some(body_id)) => {
+                    hir::TraitItemKind::Method(_, Some(body_id)) => {
                         self.visit_body(body_id);
                     }
-                    hir::TypeTraitItem(..) => {}
+                    hir::TraitItemKind::Type(..) => {}
                 }
             }
             ast_map::NodeImplItem(impl_item) => {
@@ -358,6 +358,8 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a,
         }
     }
 
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {}
+
     fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
         // processed in visit_item above
     }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index c5b03a4a32a..443770e61b6 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -266,7 +266,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
         // methods in an impl can reuse label names.
         let saved = replace(&mut self.labels_in_fn, vec![]);
 
-        if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
+        if let hir::TraitItemKind::Method(ref sig, None) = trait_item.node {
             self.visit_early_late(
                 trait_item.id,
                 &sig.decl, &sig.generics,
diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs
index 3576ae662a0..3c5a91f4ff0 100644
--- a/src/librustc/mir/transform.rs
+++ b/src/librustc/mir/transform.rs
@@ -48,7 +48,7 @@ impl<'a, 'tcx> MirSource {
 
         match tcx.map.get(id) {
             map::NodeItem(&Item { node: ItemConst(..), .. }) |
-            map::NodeTraitItem(&TraitItem { node: ConstTraitItem(..), .. }) |
+            map::NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
             map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
                 MirSource::Const(id)
             }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 180141d674a..67137470098 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1212,7 +1212,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
             }
             Some(ast_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
-                    hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => {
+                    hir::TraitItemKind::Type(..) | hir::TraitItemKind::Const(..) => {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the trait
                         let trait_id = tcx.map.get_parent(id);
@@ -1221,7 +1221,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
                                                             trait_def_id,
                                                             tcx.region_maps.item_extent(id))
                     }
-                    hir::MethodTraitItem(_, ref body) => {
+                    hir::TraitItemKind::Method(_, ref body) => {
                         // Use call-site for extent (unless this is a
                         // trait method with no default; then fallback
                         // to the method id).
@@ -2100,10 +2100,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     }
                 }
 
-                hir::ItemTrait(.., ref trait_items) => {
-                    for trait_item in trait_items {
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    for trait_item_ref in trait_item_refs {
                         let assoc_item =
-                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item);
+                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
                         self.associated_items.borrow_mut().insert(assoc_item.def_id, assoc_item);
                     }
                 }
@@ -2121,28 +2121,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     fn associated_item_from_trait_item_ref(self,
                                            parent_def_id: DefId,
-                                           trait_item: &hir::TraitItem)
+                                           trait_item_ref: &hir::TraitItemRef)
                                            -> AssociatedItem {
-        let def_id = self.map.local_def_id(trait_item.id);
-
-        let (kind, has_self, has_value) = match trait_item.node {
-            hir::MethodTraitItem(ref sig, ref body) => {
-                (AssociatedKind::Method, sig.decl.has_self(),
-                 body.is_some())
-            }
-            hir::ConstTraitItem(_, ref value) => {
-                (AssociatedKind::Const, false, value.is_some())
-            }
-            hir::TypeTraitItem(_, ref ty) => {
-                (AssociatedKind::Type, false, ty.is_some())
+        let def_id = self.map.local_def_id(trait_item_ref.id.node_id);
+        let (kind, has_self) = match trait_item_ref.kind {
+            hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
+            hir::AssociatedItemKind::Method { has_self } => {
+                (ty::AssociatedKind::Method, has_self)
             }
+            hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
         };
 
         AssociatedItem {
-            name: trait_item.name,
+            name: trait_item_ref.name,
             kind: kind,
-            vis: Visibility::from_hir(&hir::Inherited, trait_item.id, self),
-            defaultness: hir::Defaultness::Default { has_value: has_value },
+            vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self),
+            defaultness: trait_item_ref.defaultness,
             def_id: def_id,
             container: TraitContainer(parent_def_id),
             method_has_self_argument: has_self
@@ -2187,11 +2181,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             let id = self.map.as_local_node_id(def_id).unwrap();
             let item = self.map.expect_item(id);
             let vec: Vec<_> = match item.node {
-                hir::ItemTrait(.., ref trait_items) => {
-                    trait_items.iter()
-                               .map(|trait_item| trait_item.id)
-                               .map(|id| self.map.local_def_id(id))
-                               .collect()
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    trait_item_refs.iter()
+                                   .map(|trait_item_ref| trait_item_ref.id)
+                                   .map(|id| self.map.local_def_id(id.node_id))
+                                   .collect()
                 }
                 hir::ItemImpl(.., ref impl_item_refs) => {
                     impl_item_refs.iter()