about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSean Patrick Santos <SeanPatrickSantos@gmail.com>2015-03-14 12:05:00 -0600
committerSean Patrick Santos <SeanPatrickSantos@gmail.com>2015-04-23 21:02:25 -0600
commitb5499775d6bee080b3f46539d59d238de2c1726f (patch)
treeb8d5b0e9aae8d8ffcf884c9f98299ef1add06ed0
parent21f278a6877b3a66f665d86402c6ae057827a610 (diff)
downloadrust-b5499775d6bee080b3f46539d59d238de2c1726f.tar.gz
rust-b5499775d6bee080b3f46539d59d238de2c1726f.zip
Structural changes for associated constants
Introduces new variants and types in syntax::ast, middle::ty, and middle::def.
-rw-r--r--src/librustc/metadata/decoder.rs7
-rw-r--r--src/librustc/metadata/encoder.rs20
-rw-r--r--src/librustc/middle/astencode.rs3
-rw-r--r--src/librustc/middle/dead.rs13
-rw-r--r--src/librustc/middle/def.rs4
-rw-r--r--src/librustc/middle/expr_use_visitor.rs3
-rw-r--r--src/librustc/middle/infer/error_reporting.rs8
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/pat_util.rs2
-rw-r--r--src/librustc/middle/reachable.rs11
-rw-r--r--src/librustc/middle/traits/object_safety.rs4
-rw-r--r--src/librustc/middle/traits/project.rs2
-rw-r--r--src/librustc/middle/traits/util.rs6
-rw-r--r--src/librustc/middle/ty.rs84
-rw-r--r--src/librustc/util/ppaux.rs33
-rw-r--r--src/librustc_lint/builtin.rs6
-rw-r--r--src/librustc_privacy/lib.rs33
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs9
-rw-r--r--src/librustc_resolve/lib.rs10
-rw-r--r--src/librustc_trans/save/mod.rs29
-rw-r--r--src/librustc_trans/trans/base.rs36
-rw-r--r--src/librustc_trans/trans/callee.rs5
-rw-r--r--src/librustc_trans/trans/debuginfo.rs9
-rw-r--r--src/librustc_trans/trans/meth.rs24
-rw-r--r--src/librustc_trans/trans/monomorphize.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs32
-rw-r--r--src/librustc_typeck/coherence/mod.rs10
-rw-r--r--src/librustc_typeck/collect.rs98
-rw-r--r--src/librustc_typeck/diagnostics.rs1
-rw-r--r--src/librustdoc/clean/inline.rs1
-rw-r--r--src/librustdoc/clean/mod.rs27
-rw-r--r--src/librustdoc/html/item_type.rs3
-rw-r--r--src/librustdoc/html/render.rs79
-rw-r--r--src/librustdoc/passes.rs3
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ast_map/blocks.rs3
-rw-r--r--src/libsyntax/ast_map/mod.rs8
-rw-r--r--src/libsyntax/fold.rs7
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/libsyntax/visit.rs10
40 files changed, 416 insertions, 243 deletions
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index cbd54256770..8e3f77f949b 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -951,11 +951,8 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
                                                     cdata,
                                                     did.node,
                                                     tcx);
-            match trait_item {
-                ty::MethodTraitItem(ref method) => {
-                    result.push((*method).clone())
-                }
-                ty::TypeTraitItem(_) => {}
+            if let ty::MethodTraitItem(ref method) = trait_item {
+                result.push((*method).clone())
             }
         }
         true
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 29270bd6c62..5f31e24a063 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -378,14 +378,11 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
                     let impl_item = ty::impl_or_trait_item(
                         ecx.tcx,
                         method_did.def_id());
-                    match impl_item {
-                        ty::MethodTraitItem(ref m) => {
-                            encode_reexported_static_method(rbml_w,
-                                                            exp,
-                                                            m.def_id,
-                                                            m.name);
-                        }
-                        ty::TypeTraitItem(_) => {}
+                    if let ty::MethodTraitItem(ref m) = impl_item {
+                        encode_reexported_static_method(rbml_w,
+                                                        exp,
+                                                        m.def_id,
+                                                        m.name);
                     }
                 }
             }
@@ -1195,6 +1192,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         for &item_def_id in items {
             rbml_w.start_tag(tag_item_impl_item);
             match item_def_id {
+                ty::ConstTraitItemId(_) => {}
                 ty::MethodTraitItemId(item_def_id) => {
                     encode_def_id(rbml_w, item_def_id);
                     encode_item_sort(rbml_w, 'r');
@@ -1232,6 +1230,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             });
 
             match ty::impl_or_trait_item(tcx, trait_item_def_id.def_id()) {
+                ty::ConstTraitItem(_) => {}
                 ty::MethodTraitItem(ref method_type) => {
                     encode_info_for_method(ecx,
                                            rbml_w,
@@ -1276,6 +1275,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         for &method_def_id in &*ty::trait_item_def_ids(tcx, def_id) {
             rbml_w.start_tag(tag_item_trait_item);
             match method_def_id {
+                ty::ConstTraitItemId(_) => {}
                 ty::MethodTraitItemId(method_def_id) => {
                     encode_def_id(rbml_w, method_def_id);
                     encode_item_sort(rbml_w, 'r');
@@ -1321,6 +1321,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 ty::impl_or_trait_item(tcx, item_def_id.def_id());
             let is_nonstatic_method;
             match trait_item_type {
+                ty::ConstTraitItem(_) => {
+                    is_nonstatic_method = false;
+                }
                 ty::MethodTraitItem(method_ty) => {
                     let method_def_id = item_def_id.def_id();
 
@@ -1365,6 +1368,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             let trait_item = &*ms[i];
             encode_attributes(rbml_w, &trait_item.attrs);
             match trait_item.node {
+                ast::ConstTraitItem(_, _) => {}
                 ast::MethodTraitItem(ref sig, ref body) => {
                     // If this is a static method, we've already
                     // encoded this.
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index ee8373279d9..61b610ab655 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -465,6 +465,9 @@ impl tr for def::Def {
           def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
           def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
           def::DefConst(did) => { def::DefConst(did.tr(dcx)) }
+          def::DefAssociatedConst(did, p) => {
+              def::DefAssociatedConst(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
+          }
           def::DefLocal(nid) => { def::DefLocal(dcx.tr_id(nid)) }
           def::DefVariant(e_did, v_did, is_s) => {
             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 2befbf99245..fc40febdbf8 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
         self.tcx.def_map.borrow().get(id).map(|def| {
             match def.full_def() {
-                def::DefConst(_) => {
+                def::DefConst(_) | def::DefAssociatedConst(..) => {
                     self.check_def_id(def.def_id())
                 }
                 _ if self.ignore_non_const_paths => (),
@@ -114,14 +114,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                         let trait_item = ty::trait_item(self.tcx,
                                                         trait_ref.def_id,
                                                         index);
-                        match trait_item {
-                            ty::MethodTraitItem(method) => {
-                                self.check_def_id(method.def_id);
-                            }
-                            ty::TypeTraitItem(typedef) => {
-                                self.check_def_id(typedef.def_id);
-                            }
-                        }
+                        self.check_def_id(trait_item.def_id());
                     }
                 }
             }
@@ -365,6 +358,7 @@ impl<'v> Visitor<'v> for LifeSeeder {
             ast::ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => {
                 for impl_item in impl_items {
                     match impl_item.node {
+                        ast::ConstImplItem(..) => {}
                         ast::MethodImplItem(..) => {
                             if opt_trait.is_some() ||
                                     has_allow_dead_code_or_lang_attr(&impl_item.attrs) {
@@ -584,6 +578,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
     // Overwrite so that we don't warn the trait method itself.
     fn visit_trait_item(&mut self, trait_method: &ast::TraitItem) {
         match trait_method.node {
+            ast::ConstTraitItem(_, _) => {}
             ast::MethodTraitItem(_, Some(ref body)) => {
                 visit::walk_block(self, body)
             }
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index f0b35908854..bce246fa4af 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -28,6 +28,7 @@ pub enum Def {
     DefForeignMod(ast::DefId),
     DefStatic(ast::DefId, bool /* is_mutbl */),
     DefConst(ast::DefId),
+    DefAssociatedConst(ast::DefId /* const */, MethodProvenance),
     DefLocal(ast::NodeId),
     DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
     DefTy(ast::DefId, bool /* is_enum */),
@@ -140,7 +141,8 @@ impl Def {
             DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
             DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
             DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
-            DefMethod(id, _) | DefConst(id) | DefSelfTy(Some(id), None)=> {
+            DefMethod(id, _) | DefConst(id) | DefAssociatedConst(id, _) |
+            DefSelfTy(Some(id), None)=> {
                 id
             }
             DefLocal(id) |
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 5235bbdf9cf..87379bd48f0 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -234,7 +234,7 @@ impl OverloadedCallType {
             ty::MethodTraitItem(ref method_descriptor) => {
                 (*method_descriptor).clone()
             }
-            ty::TypeTraitItem(_) => {
+            _ => {
                 tcx.sess.bug("overloaded call method wasn't in method map")
             }
         };
@@ -1183,6 +1183,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         }
 
                         Some(def::DefConst(..)) |
+                        Some(def::DefAssociatedConst(..)) |
                         Some(def::DefLocal(..)) => {
                             // This is a leaf (i.e. identifier binding
                             // or constant value to match); thus no
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index 3dbbcce27b6..22e3376e09e 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -843,8 +843,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                   Some(&sig.explicit_self.node),
                                   item.span))
                         }
-                        ast::TypeImplItem(_) => None,
-                        ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro")
+                        ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro"),
+                        _ => None,
                     }
                 },
                 ast_map::NodeTraitItem(item) => {
@@ -1723,8 +1723,8 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
                         taken.push_all(&sig.generics.lifetimes);
                         Some(ii.id)
                     }
-                    ast::TypeImplItem(_) => None,
-                    ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro")
+                    ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro"),
+                    _ => None,
                 }
             }
             _ => None
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 003306fe558..6db55baf483 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -589,7 +589,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
 
         match def {
           def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
-          def::DefFn(..) | def::DefMethod(..) => {
+          def::DefAssociatedConst(..) | def::DefFn(..) | def::DefMethod(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
@@ -1286,7 +1286,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                         try!(self.cat_pattern_(cmt_field, &**subpat, op));
                     }
                 }
-                Some(def::DefConst(..)) => {
+                Some(def::DefConst(..)) | Some(def::DefAssociatedConst(..)) => {
                     for subpat in subpats {
                         try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
                     }
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 12b56562c84..7a0f58947fe 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -62,7 +62,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
     match pat.node {
         ast::PatIdent(_, _, None) | ast::PatEnum(..) => {
             match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) => true,
+                Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
                 _ => false
             }
         }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 1bd45b5fc86..b532dc88df4 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -113,7 +113,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
                             // If this path leads to a constant, then we need to
                             // recurse into the constant to continue finding
                             // items that are reachable.
-                            def::DefConst(..) => {
+                            def::DefConst(..) | def::DefAssociatedConst(..) => {
                                 self.worklist.push(def_id.node);
                             }
 
@@ -183,12 +183,14 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             }
             Some(ast_map::NodeTraitItem(trait_method)) => {
                 match trait_method.node {
+                    ast::ConstTraitItem(_, ref default) => default.is_some(),
                     ast::MethodTraitItem(_, ref body) => body.is_some(),
                     ast::TypeTraitItem(..) => false,
                 }
             }
             Some(ast_map::NodeImplItem(impl_item)) => {
                 match impl_item.node {
+                    ast::ConstImplItem(..) => true,
                     ast::MethodImplItem(ref sig, _) => {
                         if generics_require_inlining(&sig.generics) ||
                                 attr::requests_inline(&impl_item.attrs) {
@@ -303,9 +305,13 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             }
             ast_map::NodeTraitItem(trait_method) => {
                 match trait_method.node {
+                    ast::ConstTraitItem(_, None) |
                     ast::MethodTraitItem(_, None) => {
                         // Keep going, nothing to get exported
                     }
+                    ast::ConstTraitItem(_, Some(ref expr)) => {
+                        self.visit_expr(&*expr);
+                    }
                     ast::MethodTraitItem(_, Some(ref body)) => {
                         visit::walk_block(self, body);
                     }
@@ -314,6 +320,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             }
             ast_map::NodeImplItem(impl_item) => {
                 match impl_item.node {
+                    ast::ConstImplItem(_, ref expr) => {
+                        self.visit_expr(&*expr);
+                    }
                     ast::MethodImplItem(ref sig, ref body) => {
                         let did = self.tcx.map.get_parent_did(search_item);
                         if method_might_be_inlined(self.tcx, sig, impl_item, did) {
diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs
index a2ff86cd065..3d6ed3c3440 100644
--- a/src/librustc/middle/traits/object_safety.rs
+++ b/src/librustc/middle/traits/object_safety.rs
@@ -100,9 +100,7 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
                         .map(|code| ObjectSafetyViolation::Method(m.clone(), code))
                         .into_iter()
                 }
-                ty::TypeTraitItem(_) => {
-                    None.into_iter()
-                }
+                _ => None.into_iter(),
             }
         })
         .collect();
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index 7488b8f046e..9cdae21868e 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -863,7 +863,7 @@ fn confirm_impl_candidate<'cx,'tcx>(
     for impl_item in impl_items {
         let assoc_type = match *impl_or_trait_items_map.get(&impl_item.def_id()).unwrap() {
             ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
-            ty::MethodTraitItem(..) => { continue; }
+            ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => { continue; }
         };
 
         if assoc_type.name != obligation.predicate.item_name {
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index ddf941198eb..6ecff3b7faa 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -434,7 +434,7 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         for trait_item in &**trait_items {
             match *trait_item {
                 ty::MethodTraitItem(_) => method_count += 1,
-                ty::TypeTraitItem(_) => {}
+                _ => {}
             }
         }
     }
@@ -445,14 +445,14 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     for trait_item in trait_items.iter().take(method_offset_in_trait) {
         match *trait_item {
             ty::MethodTraitItem(_) => method_count += 1,
-            ty::TypeTraitItem(_) => {}
+            _ => {}
         }
     }
 
     // the item at the offset we were given really ought to be a method
     assert!(match trait_items[method_offset_in_trait] {
         ty::MethodTraitItem(_) => true,
-        ty::TypeTraitItem(_) => false
+        _ => false
     });
 
     method_count
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 2c94399f921..3f5f40ec0b5 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -131,6 +131,7 @@ impl ImplOrTraitItemContainer {
 
 #[derive(Clone, Debug)]
 pub enum ImplOrTraitItem<'tcx> {
+    ConstTraitItem(Rc<AssociatedConst<'tcx>>),
     MethodTraitItem(Rc<Method<'tcx>>),
     TypeTraitItem(Rc<AssociatedType>),
 }
@@ -138,6 +139,9 @@ pub enum ImplOrTraitItem<'tcx> {
 impl<'tcx> ImplOrTraitItem<'tcx> {
     fn id(&self) -> ImplOrTraitItemId {
         match *self {
+            ConstTraitItem(ref associated_const) => {
+                ConstTraitItemId(associated_const.def_id)
+            }
             MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
             TypeTraitItem(ref associated_type) => {
                 TypeTraitItemId(associated_type.def_id)
@@ -147,6 +151,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> {
 
     pub fn def_id(&self) -> ast::DefId {
         match *self {
+            ConstTraitItem(ref associated_const) => associated_const.def_id,
             MethodTraitItem(ref method) => method.def_id,
             TypeTraitItem(ref associated_type) => associated_type.def_id,
         }
@@ -154,13 +159,23 @@ impl<'tcx> ImplOrTraitItem<'tcx> {
 
     pub fn name(&self) -> ast::Name {
         match *self {
+            ConstTraitItem(ref associated_const) => associated_const.name,
             MethodTraitItem(ref method) => method.name,
             TypeTraitItem(ref associated_type) => associated_type.name,
         }
     }
 
+    pub fn vis(&self) -> ast::Visibility {
+        match *self {
+            ConstTraitItem(ref associated_const) => associated_const.vis,
+            MethodTraitItem(ref method) => method.vis,
+            TypeTraitItem(ref associated_type) => associated_type.vis,
+        }
+    }
+
     pub fn container(&self) -> ImplOrTraitItemContainer {
         match *self {
+            ConstTraitItem(ref associated_const) => associated_const.container,
             MethodTraitItem(ref method) => method.container,
             TypeTraitItem(ref associated_type) => associated_type.container,
         }
@@ -169,13 +184,14 @@ impl<'tcx> ImplOrTraitItem<'tcx> {
     pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
         match *self {
             MethodTraitItem(ref m) => Some((*m).clone()),
-            TypeTraitItem(_) => None
+            _ => None,
         }
     }
 }
 
 #[derive(Clone, Copy, Debug)]
 pub enum ImplOrTraitItemId {
+    ConstTraitItemId(ast::DefId),
     MethodTraitItemId(ast::DefId),
     TypeTraitItemId(ast::DefId),
 }
@@ -183,6 +199,7 @@ pub enum ImplOrTraitItemId {
 impl ImplOrTraitItemId {
     pub fn def_id(&self) -> ast::DefId {
         match *self {
+            ConstTraitItemId(def_id) => def_id,
             MethodTraitItemId(def_id) => def_id,
             TypeTraitItemId(def_id) => def_id,
         }
@@ -237,6 +254,16 @@ impl<'tcx> Method<'tcx> {
 }
 
 #[derive(Clone, Copy, Debug)]
+pub struct AssociatedConst<'tcx> {
+    pub name: ast::Name,
+    pub ty: Ty<'tcx>,
+    pub vis: ast::Visibility,
+    pub def_id: ast::DefId,
+    pub container: ImplOrTraitItemContainer,
+    pub default: Option<ast::DefId>,
+}
+
+#[derive(Clone, Copy, Debug)]
 pub struct AssociatedType {
     pub name: ast::Name,
     pub vis: ast::Visibility,
@@ -2273,6 +2300,16 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
         match cx.map.find(id) {
             Some(ast_map::NodeImplItem(ref impl_item)) => {
                 match impl_item.node {
+                    ast::ConstImplItem(_, _) => {
+                        let def_id = ast_util::local_def(id);
+                        let scheme = lookup_item_type(cx, def_id);
+                        let predicates = lookup_predicates(cx, def_id);
+                        construct_parameter_environment(cx,
+                                                        impl_item.span,
+                                                        &scheme.generics,
+                                                        &predicates,
+                                                        id)
+                    }
                     ast::MethodImplItem(_, ref body) => {
                         let method_def_id = ast_util::local_def(id);
                         match ty::impl_or_trait_item(cx, method_def_id) {
@@ -2286,11 +2323,10 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                     method_bounds,
                                     body.id)
                             }
-                            TypeTraitItem(_) => {
+                            _ => {
                                 cx.sess
                                   .bug("ParameterEnvironment::for_item(): \
-                                        can't create a parameter environment \
-                                        for type trait items")
+                                        got non-method item from impl method?!")
                             }
                         }
                     }
@@ -2304,6 +2340,25 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
             }
             Some(ast_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
+                    ast::ConstTraitItem(_, ref default) => {
+                        match *default {
+                            Some(_) => {
+                                let def_id = ast_util::local_def(id);
+                                let scheme = lookup_item_type(cx, def_id);
+                                let predicates = lookup_predicates(cx, def_id);
+                                construct_parameter_environment(cx,
+                                                                trait_item.span,
+                                                                &scheme.generics,
+                                                                &predicates,
+                                                                id)
+                            }
+                            None => {
+                                cx.sess.bug("ParameterEnvironment::from_item(): \
+                                             can't create a parameter environment \
+                                             for const trait items without defaults")
+                            }
+                        }
+                    }
                     ast::MethodTraitItem(_, None) => {
                         cx.sess.span_bug(trait_item.span,
                                          "ParameterEnvironment::for_item():
@@ -2324,11 +2379,11 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                     method_bounds,
                                     body.id)
                             }
-                            TypeTraitItem(_) => {
+                            _ => {
                                 cx.sess
                                   .bug("ParameterEnvironment::for_item(): \
-                                        can't create a parameter environment \
-                                        for type trait items")
+                                        got non-method item from provided \
+                                        method?!")
                             }
                         }
                     }
@@ -4700,7 +4755,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
                 def::DefUpvar(..) |
                 def::DefLocal(..) => LvalueExpr,
 
-                def::DefConst(..) => RvalueDatumExpr,
+                def::DefConst(..) |
+                def::DefAssociatedConst(..) => RvalueDatumExpr,
 
                 def => {
                     tcx.sess.span_bug(
@@ -5051,10 +5107,10 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                 if let ast::MethodTraitItem(_, Some(_)) = ti.node {
                     match impl_or_trait_item(cx, ast_util::local_def(ti.id)) {
                         MethodTraitItem(m) => Some(m),
-                        TypeTraitItem(_) => {
+                        _ => {
                             cx.sess.bug("provided_trait_methods(): \
-                                         associated type found from \
-                                         looking up ProvidedMethod?!")
+                                         non-method item found from \
+                                         looking up provided method?!")
                         }
                     }
                 } else {
@@ -5155,7 +5211,7 @@ pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
                 Some(ref item) => {
                     match **item {
                         TypeTraitItem(_) => true,
-                        MethodTraitItem(_) => false,
+                        _ => false,
                     }
                 }
                 None => false,
@@ -6169,7 +6225,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
                            .insert(method_def_id, source);
                     }
                 }
-                TypeTraitItem(_) => {}
+                _ => {}
             }
         }
 
@@ -6221,7 +6277,7 @@ pub fn populate_implementations_for_trait_if_necessary(
                             .insert(method_def_id, source);
                     }
                 }
-                TypeTraitItem(_) => {}
+                _ => {}
             }
         }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 12a6d584857..3d56371dd52 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -830,6 +830,7 @@ impl<'tcx> Repr<'tcx> for ty::TraitDef<'tcx> {
 impl<'tcx> Repr<'tcx> for ast::TraitItem {
     fn repr(&self, _tcx: &ctxt) -> String {
         let kind = match self.node {
+            ast::ConstTraitItem(..) => "ConstTraitItem",
             ast::MethodTraitItem(..) => "MethodTraitItem",
             ast::TypeTraitItem(..) => "TypeTraitItem",
         };
@@ -1054,9 +1055,39 @@ impl<'tcx> Repr<'tcx> for ty::Variance {
     }
 }
 
+impl<'tcx> Repr<'tcx> for ty::ImplOrTraitItem<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("ImplOrTraitItem({})",
+                match *self {
+                    ty::ImplOrTraitItem::MethodTraitItem(ref i) => i.repr(tcx),
+                    ty::ImplOrTraitItem::ConstTraitItem(ref i) => i.repr(tcx),
+                    ty::ImplOrTraitItem::TypeTraitItem(ref i) => i.repr(tcx),
+                })
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ty::AssociatedConst<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("AssociatedConst(name: {}, ty: {}, vis: {}, def_id: {})",
+                self.name.repr(tcx),
+                self.ty.repr(tcx),
+                self.vis.repr(tcx),
+                self.def_id.repr(tcx))
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ty::AssociatedType {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("AssociatedType(name: {}, vis: {}, def_id: {})",
+                self.name.repr(tcx),
+                self.vis.repr(tcx),
+                self.def_id.repr(tcx))
+    }
+}
+
 impl<'tcx> Repr<'tcx> for ty::Method<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("method(name: {}, generics: {}, predicates: {}, fty: {}, \
+        format!("Method(name: {}, generics: {}, predicates: {}, fty: {}, \
                  explicit_self: {}, vis: {}, def_id: {})",
                 self.name.repr(tcx),
                 self.generics.repr(tcx),
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index c12ac501c45..f4761f95505 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1584,8 +1584,9 @@ impl LintPass for MissingDoc {
         if self.private_traits.contains(&trait_item.id) { return }
 
         let desc = match trait_item.node {
+            ast::ConstTraitItem(..) => "an associated constant",
             ast::MethodTraitItem(..) => "a trait method",
-            ast::TypeTraitItem(..) => "an associated type"
+            ast::TypeTraitItem(..) => "an associated type",
         };
 
         self.check_missing_docs_attrs(cx, Some(trait_item.id),
@@ -1600,9 +1601,10 @@ impl LintPass for MissingDoc {
         }
 
         let desc = match impl_item.node {
+            ast::ConstImplItem(..) => "an associated constant",
             ast::MethodImplItem(..) => "a method",
             ast::TypeImplItem(_) => "an associated type",
-            ast::MacImplItem(_) => "an impl item macro"
+            ast::MacImplItem(_) => "an impl item macro",
         };
         self.check_missing_docs_attrs(cx, Some(impl_item.id),
                                       &impl_item.attrs,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 70c824a67a0..832a33e3fe0 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -272,6 +272,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
                 if public_ty || public_trait {
                     for impl_item in impl_items {
                         match impl_item.node {
+                            ast::ConstImplItem(_, _) => {}
                             ast::MethodImplItem(ref sig, _) => {
                                 let meth_public = match sig.explicit_self.node {
                                     ast::SelfStatic => public_ty,
@@ -399,6 +400,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             debug!("privacy - is {:?} a public method", did);
 
             return match self.tcx.impl_or_trait_items.borrow().get(&did) {
+                Some(&ty::ConstTraitItem(_)) => ExternallyDenied,
                 Some(&ty::MethodTraitItem(ref meth)) => {
                     debug!("privacy - well at least it's a method: {:?}",
                            *meth);
@@ -490,6 +492,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                 //               where the method was defined?
                 Some(ast_map::NodeImplItem(ii)) => {
                     match ii.node {
+                        ast::ConstImplItem(..) |
                         ast::MethodImplItem(..) => {
                             let imp = self.tcx.map
                                           .get_parent_did(closest_private_id);
@@ -693,7 +696,11 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             ty::MethodTraitItem(method_type) => {
                 method_type.provided_source.unwrap_or(method_id)
             }
-            ty::TypeTraitItem(_) => method_id,
+            _ => {
+                self.tcx.sess
+                    .span_bug(span,
+                              "got non-method item in check_static_method")
+            }
         };
 
         let string = token::get_name(name);
@@ -1128,8 +1135,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                         ast::MethodImplItem(..) => {
                             check_inherited(tcx, impl_item.span, impl_item.vis);
                         }
-                        ast::TypeImplItem(_) |
-                        ast::MacImplItem(_) => {}
+                        _ => {}
                     }
                 }
             }
@@ -1307,6 +1313,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                     impl_items.iter()
                               .any(|impl_item| {
                                   match impl_item.node {
+                                      ast::ConstImplItem(..) |
                                       ast::MethodImplItem(..) => {
                                           self.exported_items.contains(&impl_item.id)
                                       }
@@ -1330,6 +1337,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                                 // don't erroneously report errors for private
                                 // types in private items.
                                 match impl_item.node {
+                                    ast::ConstImplItem(..) |
                                     ast::MethodImplItem(..)
                                         if self.item_is_public(&impl_item.id, impl_item.vis) =>
                                     {
@@ -1360,12 +1368,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
 
                             // Those in 3. are warned with this call.
                             for impl_item in impl_items {
-                                match impl_item.node {
-                                    ast::TypeImplItem(ref ty) => {
-                                        self.visit_ty(ty);
-                                    }
-                                    ast::MethodImplItem(..) |
-                                    ast::MacImplItem(_) => {},
+                                if let ast::TypeImplItem(ref ty) = impl_item.node {
+                                    self.visit_ty(ty);
                                 }
                             }
                         }
@@ -1376,15 +1380,20 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                     let mut found_pub_static = false;
                     for impl_item in impl_items {
                         match impl_item.node {
+                            ast::ConstImplItem(..) => {
+                                if self.item_is_public(&impl_item.id, impl_item.vis) {
+                                    found_pub_static = true;
+                                    visit::walk_impl_item(self, impl_item);
+                                }
+                            }
                             ast::MethodImplItem(ref sig, _) => {
                                 if sig.explicit_self.node == ast::SelfStatic &&
-                                        self.item_is_public(&impl_item.id, impl_item.vis) {
+                                      self.item_is_public(&impl_item.id, impl_item.vis) {
                                     found_pub_static = true;
                                     visit::walk_impl_item(self, impl_item);
                                 }
                             }
-                            ast::TypeImplItem(_) |
-                            ast::MacImplItem(_) => {}
+                            _ => {}
                         }
                     }
                     if found_pub_static {
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 777154f3c9c..0d25700d2b7 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -530,6 +530,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                         trait_item.span);
 
                     match trait_item.node {
+                        ast::ConstTraitItem(..) => {
+                            let def = DefAssociatedConst(local_def(trait_item.id),
+                                                         FromTrait(local_def(item.id)));
+                            // NB: not IMPORTABLE
+                            name_bindings.define_value(def, trait_item.span, PUBLIC);
+                        }
                         ast::MethodTraitItem(..) => {
                             let def = DefMethod(local_def(trait_item.id),
                                                 FromTrait(local_def(item.id)));
@@ -703,7 +709,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
                     .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
           }
-          DefFn(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
+          DefFn(..) | DefStatic(..) | DefConst(..) | DefAssociatedConst(..) |
+          DefMethod(..) => {
             debug!("(building reduced graph for external \
                     crate) building value (fn/static) {}", final_ident);
             // impl methods have already been defined with the correct importability modifier
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index d300045c0ec..f43d951aaaa 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -60,7 +60,8 @@ use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
 use rustc::util::lev_distance::lev_distance;
 
-use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
+use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block};
+use syntax::ast::{ConstImplItem, Crate, CrateNum};
 use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
 use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall};
 use syntax::ast::{ExprPath, ExprStruct, FnDecl};
@@ -1831,6 +1832,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             // FIXME #4951: Do we need a node ID here?
 
                             let type_parameters = match trait_item.node {
+                                ast::ConstTraitItem(..) => NoTypeParameters,
                                 ast::MethodTraitItem(ref sig, _) => {
                                     HasTypeParameters(&sig.generics,
                                                       FnSpace,
@@ -2094,6 +2096,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     this.with_current_self_type(self_type, |this| {
                         for impl_item in impl_items {
                             match impl_item.node {
+                                ConstImplItem(_, _) => {}
                                 MethodImplItem(ref sig, _) => {
                                     // If this is a trait impl, ensure the method
                                     // exists in trait
@@ -2466,7 +2469,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     // This must be an enum variant, struct or const.
                     if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) {
                         match path_res.base_def {
-                            DefVariant(..) | DefStruct(..) | DefConst(..) => {
+                            DefVariant(..) | DefStruct(..) | DefConst(..) |
+                            DefAssociatedConst(..) => {
                                 self.record_def(pattern.id, path_res);
                             }
                             DefStatic(..) => {
@@ -2542,7 +2546,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             def @ DefVariant(..) | def @ DefStruct(..) => {
                                 return FoundStructOrEnumVariant(def, LastMod(AllPublic));
                             }
-                            def @ DefConst(..) => {
+                            def @ DefConst(..) | def @ DefAssociatedConst(..) => {
                                 return FoundConst(def, LastMod(AllPublic));
                             }
                             DefStatic(..) => {
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index 57dba30723f..237270da562 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -242,6 +242,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
             def::DefTrait(_) => Some(recorder::TypeRef),
             def::DefStatic(_, _) |
             def::DefConst(_) |
+            def::DefAssociatedConst(..) |
             def::DefLocal(_) |
             def::DefVariant(_, _, _) |
             def::DefUpvar(..) => Some(recorder::VarRef),
@@ -359,14 +360,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         // record the decl for this def (if it has one)
         let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx,
                                              ast_util::local_def(id))
-            .and_then(|def_id| {
-                if match def_id {
-                    ty::MethodTraitItemId(def_id) => {
-                        def_id.node != 0 && def_id != ast_util::local_def(id)
-                    }
-                    ty::TypeTraitItemId(_) => false,
-                } {
-                    Some(def_id.def_id())
+            .and_then(|new_id| {
+                let def_id = new_id.def_id();
+                if def_id.node != 0 && def_id != ast_util::local_def(id) {
+                    Some(def_id)
                 } else {
                     None
                 }
@@ -800,6 +797,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
             def::DefLocal(..) |
             def::DefStatic(..) |
             def::DefConst(..) |
+            def::DefAssociatedConst(..) |
             def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
                                                     span,
                                                     sub_span,
@@ -883,6 +881,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
             def::DefLocal(_) |
             def::DefStatic(_,_) |
             def::DefConst(..) |
+            def::DefAssociatedConst(..) |
             def::DefStruct(_) |
             def::DefVariant(..) |
             def::DefFn(..) => self.write_sub_paths_truncated(path, false),
@@ -966,7 +965,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                     ty::MethodTraitItem(method) => {
                         method.provided_source.unwrap_or(def_id)
                     }
-                    ty::TypeTraitItem(_) => def_id,
+                    _ => self.sess
+                             .span_bug(ex.span,
+                                       "save::process_method_call: non-method \
+                                        DefId in MethodStatic or MethodStaticClosure"),
                 };
                 (Some(def_id), decl_id)
             }
@@ -1008,7 +1010,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
 
                 let def = self.analysis.ty_cx.def_map.borrow().get(&p.id).unwrap().full_def();
                 let struct_def = match def {
-                    def::DefConst(..) => None,
+                    def::DefConst(..) | def::DefAssociatedConst(..) => None,
                     def::DefVariant(_, variant_id, _) => Some(variant_id),
                     _ => {
                         match ty::ty_to_def_id(ty::node_id_to_type(&self.analysis.ty_cx, p.id)) {
@@ -1236,6 +1238,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
         match trait_item.node {
+            ast::ConstTraitItem(..) => {}
             ast::MethodTraitItem(ref sig, ref body) => {
                 self.process_method(sig, body.as_ref().map(|x| &**x),
                                     trait_item.id, trait_item.ident.name, trait_item.span);
@@ -1246,6 +1249,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
 
     fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
         match impl_item.node {
+            ast::ConstImplItem(..) => {}
             ast::MethodImplItem(ref sig, ref body) => {
                 self.process_method(sig, Some(body), impl_item.id,
                                     impl_item.ident.name, impl_item.span);
@@ -1432,8 +1436,9 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                     paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
                 // FIXME(nrc) what are these doing here?
-                def::DefStatic(_, _) => {}
-                def::DefConst(..) => {}
+                def::DefStatic(_, _) |
+                def::DefConst(..) |
+                def::DefAssociatedConst(..) => {}
                 _ => error!("unexpected definition kind when processing collected paths: {:?}",
                             def)
             }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 59f3ff72602..1ceba3c8230 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -1078,25 +1078,17 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
         Some(ast_map::NodeTraitItem(trait_item)) => {
             match trait_item.node {
                 ast::MethodTraitItem(_, Some(ref body)) => body,
-                ast::MethodTraitItem(_, None) => {
-                    tcx.sess.bug("unexpected variant: required trait method \
-                                  in has_nested_returns")
-                }
-                ast::TypeTraitItem(..) => {
-                    tcx.sess.bug("unexpected variant: associated type trait item in \
-                                  has_nested_returns")
+                _ => {
+                    tcx.sess.bug("unexpected variant: trait item other than a \
+                                  provided method in has_nested_returns")
                 }
             }
         }
         Some(ast_map::NodeImplItem(impl_item)) => {
             match impl_item.node {
                 ast::MethodImplItem(_, ref body) => body,
-                ast::TypeImplItem(_) => {
-                    tcx.sess.bug("unexpected variant: associated type impl item in \
-                                  has_nested_returns")
-                }
-                ast::MacImplItem(_) => {
-                    tcx.sess.bug("unexpected variant: unexpanded macro impl item in \
+                _ => {
+                    tcx.sess.bug("unexpected variant: non-method impl item in \
                                   has_nested_returns")
                 }
             }
@@ -2363,13 +2355,14 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
         ast_map::NodeTraitItem(trait_item) => {
             debug!("get_item_val(): processing a NodeTraitItem");
             match trait_item.node {
-                ast::MethodTraitItem(_, None) | ast::TypeTraitItem(..) => {
-                    ccx.sess().span_bug(trait_item.span,
-                        "unexpected variant: required trait method in get_item_val()");
-                }
                 ast::MethodTraitItem(_, Some(_)) => {
                     register_method(ccx, id, &trait_item.attrs, trait_item.span)
                 }
+                _ => {
+                    ccx.sess().span_bug(trait_item.span,
+                        "unexpected variant: trait item other than a provided \
+                         method in get_item_val()");
+                }
             }
         }
 
@@ -2378,13 +2371,10 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                 ast::MethodImplItem(..) => {
                     register_method(ccx, id, &impl_item.attrs, impl_item.span)
                 }
-                ast::TypeImplItem(_) => {
-                    ccx.sess().span_bug(impl_item.span,
-                        "unexpected variant: associated type in get_item_val()")
-                }
-                ast::MacImplItem(_) => {
+                _ => {
                     ccx.sess().span_bug(impl_item.span,
-                        "unexpected variant: unexpanded macro in get_item_val()")
+                        "unexpected variant: non-method impl item in \
+                         get_item_val()");
                 }
             }
         }
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 0e8c33cd93a..0e468072307 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -202,6 +202,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
             }
             def::DefStatic(..) |
             def::DefConst(..) |
+            def::DefAssociatedConst(..) |
             def::DefLocal(..) |
             def::DefUpvar(..) => {
                 datum_callee(bcx, ref_expr)
@@ -465,9 +466,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
 
                     (true, source_id, new_substs)
                 }
-                ty::TypeTraitItem(_) => {
+                _ => {
                     tcx.sess.bug("trans_fn_ref_with_vtables() tried \
-                                  to translate an associated type?!")
+                                  to translate a non-method?!")
                 }
             }
         }
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index 7c769eca74a..69cd57d1bab 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -1314,15 +1314,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                      impl_item.span,
                      true)
                 }
-                ast::TypeImplItem(_) => {
-                    cx.sess().span_bug(impl_item.span,
-                                       "create_function_debug_context() \
-                                        called on associated type?!")
-                }
-                ast::MacImplItem(_) => {
+                _ => {
                     cx.sess().span_bug(impl_item.span,
                                        "create_function_debug_context() \
-                                        called on unexpanded macro?!")
+                                        called on non-method impl item?!")
                 }
             }
         }
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index e346fb0d931..fda931fde6e 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -74,8 +74,7 @@ pub fn trans_impl(ccx: &CrateContext,
                 ast::MethodImplItem(..) => {
                     visit::walk_impl_item(&mut v, impl_item);
                 }
-                ast::TypeImplItem(_) |
-                ast::MacImplItem(_) => {}
+                _ => {}
             }
         }
         return;
@@ -98,8 +97,7 @@ pub fn trans_impl(ccx: &CrateContext,
                 }
                 visit::walk_impl_item(&mut v, impl_item);
             }
-            ast::TypeImplItem(_) |
-            ast::MacImplItem(_) => {}
+            _ => {}
         }
     }
 }
@@ -336,9 +334,9 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let impl_did = vtable_impl.impl_def_id;
             let mname = match ty::trait_item(ccx.tcx(), trait_id, n_method) {
                 ty::MethodTraitItem(method) => method.name,
-                ty::TypeTraitItem(_) => {
-                    bcx.tcx().sess.bug("can't monomorphize an associated \
-                                        type")
+                _ => {
+                    bcx.tcx().sess.bug("can't monomorphize a non-method trait \
+                                        item")
                 }
             };
             let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
@@ -579,8 +577,8 @@ pub fn trans_object_shim<'a, 'tcx>(
     // Lookup the type of this method as declared in the trait and apply substitutions.
     let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) {
         ty::MethodTraitItem(method) => method,
-        ty::TypeTraitItem(_) => {
-            tcx.sess.bug("can't create a method shim for an associated type")
+        _ => {
+            tcx.sess.bug("can't create a method shim for a non-method item")
         }
     };
     let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty);
@@ -789,11 +787,11 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     trait_item_def_ids
         .iter()
 
-        // Filter out the associated types.
+        // Filter out non-method items.
         .filter_map(|item_def_id| {
             match *item_def_id {
                 ty::MethodTraitItemId(def_id) => Some(def_id),
-                ty::TypeTraitItemId(_) => None,
+                _ => None,
             }
         })
 
@@ -806,7 +804,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
             let trait_method_type = match ty::impl_or_trait_item(tcx, trait_method_def_id) {
                 ty::MethodTraitItem(m) => m,
-                ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type")
+                _ => ccx.sess().bug("should be a method, not other assoc item"),
             };
             let name = trait_method_type.name;
 
@@ -824,7 +822,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             let impl_method_def_id = method_with_name(ccx, impl_id, name);
             let impl_method_type = match ty::impl_or_trait_item(tcx, impl_method_def_id) {
                 ty::MethodTraitItem(m) => m,
-                ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type")
+                _ => ccx.sess().bug("should be a method, not other assoc item"),
             };
 
             debug!("emit_vtable_methods: impl_method_type={}",
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 1c8d020494f..03fdd0c45c1 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -236,11 +236,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     }
                     d
                 }
-                ast::TypeImplItem(_) => {
-                    ccx.sess().bug("can't monomorphize an associated type")
-                }
-                ast::MacImplItem(_) => {
-                    ccx.sess().bug("can't monomorphize an unexpanded macro")
+                _ => {
+                    ccx.sess().bug(&format!("can't monomorphize a {:?}",
+                                           map_node))
                 }
             }
         }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 348846b8ad4..47388e0e558 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -808,6 +808,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
 
         for impl_item in impl_items {
             match impl_item.node {
+                ast::ConstImplItem(_, _) => {}
                 ast::MethodImplItem(ref sig, ref body) => {
                     check_method_body(ccx, &impl_pty.generics, sig, body,
                                       impl_item.id, impl_item.span);
@@ -823,6 +824,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_item in trait_items {
             match trait_item.node {
+                ast::ConstTraitItem(_, _) => {}
                 ast::MethodTraitItem(_, None) => {
                     // Nothing to do, since required methods don't have
                     // bodies to check.
@@ -920,6 +922,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // and compatible with trait signature
     for impl_item in impl_items {
         match impl_item.node {
+            ast::ConstImplItem(_, _) => {}
             ast::MethodImplItem(_, ref body) => {
                 let impl_method_def_id = local_def(impl_item.id);
                 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
@@ -979,13 +982,15 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         match (associated_type, &typedef_ty) {
                             (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
                             _ => {
-                                // This is `span_bug` as it should have
-                                // already been caught in resolve.
-                                tcx.sess.span_bug(
-                                    impl_item.span,
-                                    &format!("item `{}` is of a different kind from its trait `{}`",
-                                             token::get_name(typedef_ty.name()),
-                                             impl_trait_ref.repr(tcx)));
+                                // Formerly `span_bug`, but it turns out that
+                                // this is not checked in resolve, so this is
+                                // the first place where we'll notice the
+                                // mismatch.
+                                span_err!(tcx.sess, impl_item.span, E0323,
+                                          "item `{}` is an associated type, \
+                                          which doesn't match its trait `{}`",
+                                          token::get_name(typedef_ty.name()),
+                                          impl_trait_ref.repr(tcx))
                             }
                         }
                     }
@@ -1012,6 +1017,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let mut missing_methods = Vec::new();
     for trait_item in &*trait_items {
         match *trait_item {
+            ty::ConstTraitItem(_) => {}
             ty::MethodTraitItem(ref trait_method) => {
                 let is_implemented =
                     impl_items.iter().any(|ii| {
@@ -1019,8 +1025,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             ast::MethodImplItem(..) => {
                                 ii.ident.name == trait_method.name
                             }
-                            ast::TypeImplItem(_) |
-                            ast::MacImplItem(_) => false,
+                            _ => false,
                         }
                     });
                 let is_provided =
@@ -1035,8 +1040,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         ast::TypeImplItem(_) => {
                             ii.ident.name == associated_type.name
                         }
-                        ast::MethodImplItem(..) |
-                        ast::MacImplItem(_) => false,
+                        _ => false,
                     }
                 });
                 if !is_implemented {
@@ -4208,7 +4212,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
         def::DefFn(id, _) | def::DefMethod(id, _) |
         def::DefStatic(id, _) | def::DefVariant(_, id, _) |
-        def::DefStruct(id) | def::DefConst(id) => {
+        def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => {
             (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
         }
         def::DefTrait(_) |
@@ -4351,6 +4355,10 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
         }
 
+        def::DefAssociatedConst(..) => {
+            segment_spaces = repeat(None).take(segments.len()).collect();
+        }
+
         // Other cases. Various nonsense that really shouldn't show up
         // here. If they do, an error will have been reported
         // elsewhere. (I hope)
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index b0c994f7f64..fbfe73674e1 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -20,8 +20,9 @@ use metadata::csearch::{each_impl, get_impl_trait};
 use metadata::csearch;
 use middle::subst::{self, Subst};
 use middle::ty::RegionEscape;
-use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
-use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
+use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
+use middle::ty::{MethodTraitItemId, TypeTraitItemId};
+use middle::ty::{ParameterEnvironment, lookup_item_type};
 use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
 use middle::ty::{ty_param, TypeScheme, ty_ptr};
 use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
@@ -278,6 +279,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 let mut items: Vec<ImplOrTraitItemId> =
                         impl_items.iter().map(|impl_item| {
                     match impl_item.node {
+                        ast::ConstImplItem(..) => {
+                            ConstTraitItemId(local_def(impl_item.id))
+                        }
                         ast::MethodImplItem(..) => {
                             MethodTraitItemId(local_def(impl_item.id))
                         }
@@ -348,7 +352,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                            .insert(item_def_id.def_id(), source);
                     }
                 }
-                ty::TypeTraitItem(_) => {}
+                _ => {}
             }
         }
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 5ed93703d97..d04e447a460 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -196,7 +196,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
         let def_id = local_def(method_id);
         match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
             ty::MethodTraitItem(ref mty) => mty.clone(),
-            ty::TypeTraitItem(..) => {
+            _ => {
                 self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
             }
         }
@@ -830,43 +830,37 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
 
             // Convert all the associated types.
             for impl_item in impl_items {
-                match impl_item.node {
-                    ast::TypeImplItem(ref ty) => {
-                        if opt_trait_ref.is_none() {
-                            span_err!(tcx.sess, impl_item.span, E0202,
-                                              "associated items are not allowed in inherent impls");
-                        }
-
-                        as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
-                                                impl_item.ident, impl_item.id, impl_item.vis);
-
-                        let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
-                        tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
-                                                       TypeScheme {
-                                                           generics: ty::Generics::empty(),
-                                                           ty: typ,
-                                                       });
-                        tcx.predicates.borrow_mut().insert(local_def(impl_item.id),
-                                                           ty::GenericPredicates::empty());
-                        write_ty_to_tcx(tcx, impl_item.id, typ);
+                if let ast::TypeImplItem(ref ty) = impl_item.node {
+                    if opt_trait_ref.is_none() {
+                        span_err!(tcx.sess, impl_item.span, E0202,
+                                  "associated items are not allowed in inherent impls");
                     }
-                    ast::MethodImplItem(..) |
-                    ast::MacImplItem(_) => {}
+
+                    as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
+                                        impl_item.ident, impl_item.id, impl_item.vis);
+
+                    let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
+                    tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
+                                                   TypeScheme {
+                                                       generics: ty::Generics::empty(),
+                                                       ty: typ,
+                                                   });
+                    tcx.predicates.borrow_mut().insert(local_def(impl_item.id),
+                                                       ty::GenericPredicates::empty());
+                    write_ty_to_tcx(tcx, impl_item.id, typ);
                 }
             }
 
             let methods = impl_items.iter().filter_map(|ii| {
-                match ii.node {
-                    ast::MethodImplItem(ref sig, _) => {
-                        // if the method specifies a visibility, use that, otherwise
-                        // inherit the visibility from the impl (so `foo` in `pub impl
-                        // { fn foo(); }` is public, but private in `priv impl { fn
-                        // foo(); }`).
-                        let method_vis = ii.vis.inherit_from(parent_visibility);
-                        Some((sig, ii.id, ii.ident, method_vis, ii.span))
-                    }
-                    ast::TypeImplItem(_) |
-                    ast::MacImplItem(_) => None
+                if let ast::MethodImplItem(ref sig, _) = ii.node {
+                    // if the method specifies a visibility, use that, otherwise
+                    // inherit the visibility from the impl (so `foo` in `pub impl
+                    // { fn foo(); }` is public, but private in `priv impl { fn
+                    // foo(); }`).
+                    let method_vis = ii.vis.inherit_from(parent_visibility);
+                    Some((sig, ii.id, ii.ident, method_vis, ii.span))
+                } else {
+                    None
                 }
             });
             convert_methods(ccx,
@@ -877,18 +871,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                             &ty_predicates);
 
             for impl_item in impl_items {
-                match impl_item.node {
-                    ast::MethodImplItem(ref sig, ref body) => {
-                        let body_id = body.id;
-                        check_method_self_type(ccx,
-                                               &BindingRscope::new(),
-                                               ccx.method_ty(impl_item.id),
-                                               selfty,
-                                               &sig.explicit_self,
-                                               body_id);
-                    }
-                    ast::TypeImplItem(_) |
-                    ast::MacImplItem(_) => {}
+                if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
+                    let body_id = body.id;
+                    check_method_self_type(ccx,
+                                           &BindingRscope::new(),
+                                           ccx.method_ty(impl_item.id),
+                                           selfty,
+                                           &sig.explicit_self,
+                                           body_id);
                 }
             }
 
@@ -919,18 +909,18 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             // Convert all the associated types.
             for trait_item in trait_items {
                 match trait_item.node {
-                    ast::MethodTraitItem(..) => {}
                     ast::TypeTraitItem(..) => {
                         as_refsociated_type(ccx, TraitContainer(local_def(it.id)),
                                                 trait_item.ident, trait_item.id, ast::Public);
                     }
+                    _ => {}
                 }
             };
 
             let methods = trait_items.iter().filter_map(|ti| {
                 let sig = match ti.node {
                     ast::MethodTraitItem(ref sig, _) => sig,
-                    ast::TypeTraitItem(..) => return None,
+                    _ => return None,
                 };
                 Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
             });
@@ -947,6 +937,9 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
                 let def_id = local_def(trait_item.id);
                 match trait_item.node {
+                    ast::ConstTraitItem(..) => {
+                        ty::ConstTraitItemId(def_id)
+                    }
                     ast::MethodTraitItem(..) => {
                         ty::MethodTraitItemId(def_id)
                     }
@@ -962,7 +955,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             for trait_item in trait_items {
                 let sig = match trait_item.node {
                     ast::MethodTraitItem(ref sig, _) => sig,
-                    ast::TypeTraitItem(..) => continue
+                    _ => continue
                 };
                 check_method_self_type(ccx,
                                        &BindingRscope::new(),
@@ -1185,8 +1178,8 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
         match trait_item.node {
-            ast::MethodTraitItem(..) => None,
             ast::TypeTraitItem(..) => Some(trait_item.ident.name),
+            _ => None,
         }
     }).collect();
 
@@ -1260,7 +1253,7 @@ fn trait_defines_associated_type_named(ccx: &CrateCtxt,
     trait_items.iter().any(|trait_item| {
         match trait_item.node {
             ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
-            ast::MethodTraitItem(..) => false,
+            _ => false,
         }
     })
 }
@@ -1320,7 +1313,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
         trait_items.iter().flat_map(|trait_item| {
             let bounds = match trait_item.node {
                 ast::TypeTraitItem(ref bounds, _) => bounds,
-                ast::MethodTraitItem(..) => {
+                _ => {
                     return vec!().into_iter();
                 }
             };
@@ -2227,7 +2220,8 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
         impl_items.iter()
                   .filter_map(|item| match item.node {
                       ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)),
-                      ast::MethodImplItem(..) | ast::MacImplItem(..) => None,
+                      ast::ConstImplItem(..) | ast::MethodImplItem(..) |
+                      ast::MacImplItem(..) => None,
                   })
                   .flat_map(|ty| ctp::parameters_for_type(ty).into_iter())
                   .filter_map(|p| match p {
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index b17702cfb8c..b17a7f4f318 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -176,6 +176,7 @@ register_diagnostics! {
     E0320, // recursive overflow during dropck
     E0321, // extended coherence rules for defaulted traits violated
     E0322, // cannot implement Sized explicitly
+    E0323, // implemented trait where method should have been provided
     E0366, // dropck forbid specialization to concrete type or region
     E0367, // dropck forbid specialization to predicate not in struct/enum
     E0368, // binary operation `<op>=` cannot be applied to types
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4fc86cf181b..0bc3da416cb 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -312,6 +312,7 @@ pub fn build_impl(cx: &DocContext,
         let did = did.def_id();
         let impl_item = ty::impl_or_trait_item(tcx, did);
         match impl_item {
+            ty::ConstTraitItem(_) => { return None }
             ty::MethodTraitItem(method) => {
                 if method.vis != ast::Public && associated_trait.is_none() {
                     return None
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 23c9edde77c..73fbfe29224 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -361,6 +361,7 @@ pub enum ItemEnum {
     ForeignStaticItem(Static),
     MacroItem(Macro),
     PrimitiveItem(PrimitiveType),
+    AssociatedConstItem(Type, Option<String>),
     AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
     DefaultImplItem(DefaultImpl),
 }
@@ -1235,6 +1236,11 @@ impl Clean<PolyTrait> for ast::PolyTraitRef {
 impl Clean<Item> for ast::TraitItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
+            ast::ConstTraitItem(ref ty, ref default) => {
+                AssociatedConstItem(ty.clean(cx),
+                                    default.as_ref().map(|expr|
+                                                         expr.span.to_src(cx)))
+            }
             ast::MethodTraitItem(ref sig, Some(_)) => {
                 MethodItem(sig.clean(cx))
             }
@@ -1260,6 +1266,12 @@ impl Clean<Item> for ast::TraitItem {
 impl Clean<Item> for ast::ImplItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
+            ast::ConstImplItem(ref ty, ref expr) => {
+                ConstantItem(Constant{
+                    type_: ty.clean(cx),
+                    expr: expr.span.to_src(cx),
+                })
+            }
             ast::MethodImplItem(ref sig, _) => {
                 MethodItem(sig.clean(cx))
             }
@@ -1363,6 +1375,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
 impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         match *self {
+            ty::ConstTraitItem(ref cti) => cti.clean(cx),
             ty::MethodTraitItem(ref mti) => mti.clean(cx),
             ty::TypeTraitItem(ref tti) => tti.clean(cx),
         }
@@ -2672,6 +2685,20 @@ impl Clean<Stability> for attr::Stability {
     }
 }
 
+impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            source: DUMMY_SP.clean(cx),
+            name: Some(self.name.clean(cx)),
+            attrs: Vec::new(),
+            inner: AssociatedConstItem(self.ty.clean(cx), None),
+            visibility: None,
+            def_id: self.def_id,
+            stability: None,
+        }
+    }
+}
+
 impl Clean<Item> for ty::AssociatedType {
     fn clean(&self, cx: &DocContext) -> Item {
         // When loading a cross-crate associated type, the bounds for this type
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index d2385702a73..afc93f41172 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -39,6 +39,7 @@ pub enum ItemType {
     Primitive       = 15,
     AssociatedType  = 16,
     Constant        = 17,
+    AssociatedConst = 18,
 }
 
 impl ItemType {
@@ -63,6 +64,7 @@ impl ItemType {
             clean::ForeignStaticItem(..)   => ItemType::Static, // no ForeignStatic
             clean::MacroItem(..)           => ItemType::Macro,
             clean::PrimitiveItem(..)       => ItemType::Primitive,
+            clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
             clean::AssociatedTypeItem(..)  => ItemType::AssociatedType,
             clean::DefaultImplItem(..)     => ItemType::Impl,
         }
@@ -102,6 +104,7 @@ impl ItemType {
             ItemType::Primitive       => "primitive",
             ItemType::AssociatedType  => "associatedtype",
             ItemType::Constant        => "constant",
+            ItemType::AssociatedConst => "associatedconstant",
         }
     }
 }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 1993f03efd1..447cf7eab45 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1629,6 +1629,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
                 ItemType::Macro           => ("macros", "Macros"),
                 ItemType::Primitive       => ("primitives", "Primitive Types"),
                 ItemType::AssociatedType  => ("associated-types", "Associated Types"),
+                ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
             };
             try!(write!(w,
                         "<h2 id='{id}' class='section-header'>\
@@ -1799,7 +1800,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         try!(write!(w, "{{\n"));
         for t in &types {
             try!(write!(w, "    "));
-            try!(render_method(w, t, MethodLink::Anchor));
+            try!(render_assoc_item(w, t, AssocItemLink::Anchor));
             try!(write!(w, ";\n"));
         }
         if !types.is_empty() && !required.is_empty() {
@@ -1807,7 +1808,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &required {
             try!(write!(w, "    "));
-            try!(render_method(w, m, MethodLink::Anchor));
+            try!(render_assoc_item(w, m, AssocItemLink::Anchor));
             try!(write!(w, ";\n"));
         }
         if !required.is_empty() && !provided.is_empty() {
@@ -1815,7 +1816,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &provided {
             try!(write!(w, "    "));
-            try!(render_method(w, m, MethodLink::Anchor));
+            try!(render_assoc_item(w, m, AssocItemLink::Anchor));
             try!(write!(w, " {{ ... }}\n"));
         }
         try!(write!(w, "}}"));
@@ -1831,7 +1832,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                     ty = shortty(m),
                     name = *m.name.as_ref().unwrap(),
                     stab = m.stability_class()));
-        try!(render_method(w, m, MethodLink::Anchor));
+        try!(render_assoc_item(w, m, AssocItemLink::Anchor));
         try!(write!(w, "</code></h3>"));
         try!(document(w, m));
         Ok(())
@@ -1871,7 +1872,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     }
 
     // If there are methods directly on this trait object, render them here.
-    try!(render_methods(w, it.def_id, MethodRender::All));
+    try!(render_assoc_items(w, it.def_id, AssocItemRender::All));
 
     let cache = cache();
     try!(write!(w, "
@@ -1917,19 +1918,19 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
-fn render_method(w: &mut fmt::Formatter, meth: &clean::Item,
-                 link: MethodLink) -> fmt::Result {
+fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
+                     link: AssocItemLink) -> fmt::Result {
     fn method(w: &mut fmt::Formatter, it: &clean::Item,
               unsafety: ast::Unsafety, abi: abi::Abi,
               g: &clean::Generics, selfty: &clean::SelfTy,
-              d: &clean::FnDecl, link: MethodLink) -> fmt::Result {
+              d: &clean::FnDecl, link: AssocItemLink) -> fmt::Result {
         use syntax::abi::Abi;
 
         let name = it.name.as_ref().unwrap();
         let anchor = format!("#{}.{}", shortty(it), name);
         let href = match link {
-            MethodLink::Anchor => anchor,
-            MethodLink::GotoSource(did) => {
+            AssocItemLink::Anchor => anchor,
+            AssocItemLink::GotoSource(did) => {
                 href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
             }
         };
@@ -1958,10 +1959,11 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item,
             method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl,
                    link)
         }
+        clean::AssociatedConstItem(_, _) => Ok(()),
         clean::AssociatedTypeItem(ref bounds, ref default) => {
             assoc_type(w, meth, bounds, default)
         }
-        _ => panic!("render_method called on non-method")
+        _ => panic!("render_assoc_item called on non-associated-item")
     }
 }
 
@@ -2001,7 +2003,7 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item,
             try!(write!(w, "</table>"));
         }
     }
-    render_methods(w, it.def_id, MethodRender::All)
+    render_assoc_items(w, it.def_id, AssocItemRender::All)
 }
 
 fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
@@ -2100,7 +2102,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
         try!(write!(w, "</table>"));
 
     }
-    try!(render_methods(w, it.def_id, MethodRender::All));
+    try!(render_assoc_items(w, it.def_id, AssocItemRender::All));
     Ok(())
 }
 
@@ -2184,19 +2186,19 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
 }
 
 #[derive(Copy, Clone)]
-enum MethodLink {
+enum AssocItemLink {
     Anchor,
     GotoSource(ast::DefId),
 }
 
-enum MethodRender<'a> {
+enum AssocItemRender<'a> {
     All,
     DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type },
 }
 
-fn render_methods(w: &mut fmt::Formatter,
-                  it: ast::DefId,
-                  what: MethodRender) -> fmt::Result {
+fn render_assoc_items(w: &mut fmt::Formatter,
+                      it: ast::DefId,
+                      what: AssocItemRender) -> fmt::Result {
     let c = cache();
     let v = match c.impls.get(&it) {
         Some(v) => v,
@@ -2207,21 +2209,21 @@ fn render_methods(w: &mut fmt::Formatter,
     });
     if !non_trait.is_empty() {
         let render_header = match what {
-            MethodRender::All => {
+            AssocItemRender::All => {
                 try!(write!(w, "<h2 id='methods'>Methods</h2>"));
                 true
             }
-            MethodRender::DerefFor { trait_, type_ } => {
+            AssocItemRender::DerefFor { trait_, type_ } => {
                 try!(write!(w, "<h2 id='deref-methods'>Methods from \
                                     {}&lt;Target={}&gt;</h2>", trait_, type_));
                 false
             }
         };
         for i in &non_trait {
-            try!(render_impl(w, i, MethodLink::Anchor, render_header));
+            try!(render_impl(w, i, AssocItemLink::Anchor, render_header));
         }
     }
-    if let MethodRender::DerefFor { .. } = what {
+    if let AssocItemRender::DerefFor { .. } = what {
         return Ok(())
     }
     if !traits.is_empty() {
@@ -2243,7 +2245,7 @@ fn render_methods(w: &mut fmt::Formatter,
         });
         for i in &manual {
             let did = i.trait_did().unwrap();
-            try!(render_impl(w, i, MethodLink::GotoSource(did), true));
+            try!(render_impl(w, i, AssocItemLink::GotoSource(did), true));
         }
         if !derived.is_empty() {
             try!(write!(w, "<h3 id='derived_implementations'>\
@@ -2251,7 +2253,7 @@ fn render_methods(w: &mut fmt::Formatter,
             </h3>"));
             for i in &derived {
                 let did = i.trait_did().unwrap();
-                try!(render_impl(w, i, MethodLink::GotoSource(did), true));
+                try!(render_impl(w, i, AssocItemLink::GotoSource(did), true));
             }
         }
     }
@@ -2266,14 +2268,14 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result {
             _ => None,
         }
     }).next().unwrap();
-    let what = MethodRender::DerefFor { trait_: deref_type, type_: target };
+    let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target };
     match *target {
-        clean::ResolvedPath { did, .. } => render_methods(w, did, what),
+        clean::ResolvedPath { did, .. } => render_assoc_items(w, did, what),
         _ => {
             if let Some(prim) = target.primitive_type() {
                 if let Some(c) = cache().primitive_locations.get(&prim) {
                     let did = ast::DefId { krate: *c, node: prim.to_node_id() };
-                    try!(render_methods(w, did, what));
+                    try!(render_assoc_items(w, did, what));
                 }
             }
             Ok(())
@@ -2281,7 +2283,7 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result {
     }
 }
 
-fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
+fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
                render_header: bool) -> fmt::Result {
     if render_header {
         try!(write!(w, "<h3 class='impl'><code>impl{} ",
@@ -2300,13 +2302,13 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
     }
 
     fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
-                    link: MethodLink) -> fmt::Result {
+                    link: AssocItemLink) -> fmt::Result {
         match item.inner {
             clean::MethodItem(..) | clean::TyMethodItem(..) => {
                 try!(write!(w, "<h4 id='method.{}' class='{}'><code>",
                             *item.name.as_ref().unwrap(),
                             shortty(item)));
-                try!(render_method(w, item, link));
+                try!(render_assoc_item(w, item, link));
                 try!(write!(w, "</code></h4>\n"));
             }
             clean::TypedefItem(ref tydef) => {
@@ -2317,6 +2319,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
                 try!(write!(w, "type {} = {}", name, tydef.type_));
                 try!(write!(w, "</code></h4>\n"));
             }
+            clean::AssociatedConstItem(_, _) => {}
             clean::AssociatedTypeItem(ref bounds, ref default) => {
                 let name = item.name.as_ref().unwrap();
                 try!(write!(w, "<h4 id='assoc_type.{}' class='{}'><code>",
@@ -2327,7 +2330,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
             }
             _ => panic!("can't make docs for trait item with name {:?}", item.name)
         }
-        if let MethodLink::Anchor = link {
+        if let AssocItemLink::Anchor = link {
             document(w, item)
         } else {
             Ok(())
@@ -2339,10 +2342,10 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
         try!(doctraititem(w, trait_item, link));
     }
 
-    fn render_default_methods(w: &mut fmt::Formatter,
-                              did: ast::DefId,
-                              t: &clean::Trait,
-                              i: &clean::Impl) -> fmt::Result {
+    fn render_default_items(w: &mut fmt::Formatter,
+                            did: ast::DefId,
+                            t: &clean::Trait,
+                            i: &clean::Impl) -> fmt::Result {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
             match i.items.iter().find(|m| { m.name == n }) {
@@ -2350,7 +2353,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
                 None => {}
             }
 
-            try!(doctraititem(w, trait_item, MethodLink::GotoSource(did)));
+            try!(doctraititem(w, trait_item, AssocItemLink::GotoSource(did)));
         }
         Ok(())
     }
@@ -2361,7 +2364,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
     // for them work.
     if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ {
         if let Some(t) = cache().traits.get(&did) {
-            try!(render_default_methods(w, did, t, &i.impl_));
+            try!(render_default_items(w, did, t, &i.impl_));
         }
     }
     try!(write!(w, "</div>"));
@@ -2458,7 +2461,7 @@ fn item_primitive(w: &mut fmt::Formatter,
                   it: &clean::Item,
                   _p: &clean::PrimitiveType) -> fmt::Result {
     try!(document(w, it));
-    render_methods(w, it.def_id, MethodRender::All)
+    render_assoc_items(w, it.def_id, AssocItemRender::All)
 }
 
 fn get_basic_keywords() -> &'static str {
diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs
index 53cfbb3efdd..74c16127f41 100644
--- a/src/librustdoc/passes.rs
+++ b/src/librustdoc/passes.rs
@@ -184,7 +184,8 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             // Primitives are never stripped
             clean::PrimitiveItem(..) => {}
 
-            // Associated types are never stripped
+            // Associated consts and types are never stripped
+            clean::AssociatedConstItem(..) |
             clean::AssociatedTypeItem(..) => {}
         }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 399810cb7f5..3f2e7c765a5 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1236,6 +1236,7 @@ pub struct TraitItem {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum TraitItem_ {
+    ConstTraitItem(P<Ty>, Option<P<Expr>>),
     MethodTraitItem(MethodSig, Option<P<Block>>),
     TypeTraitItem(TyParamBounds, Option<P<Ty>>),
 }
@@ -1252,6 +1253,7 @@ pub struct ImplItem {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum ImplItem_ {
+    ConstImplItem(P<Ty>, P<Expr>),
     MethodImplItem(MethodSig, P<Block>),
     TypeImplItem(P<Ty>),
     MacImplItem(Mac),
diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs
index 1505d1e91b8..36a7f3a9381 100644
--- a/src/libsyntax/ast_map/blocks.rs
+++ b/src/libsyntax/ast_map/blocks.rs
@@ -222,8 +222,7 @@ impl<'a> FnLikeNode<'a> {
                     ast::MethodImplItem(ref sig, ref body) => {
                         method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span)
                     }
-                    ast::TypeImplItem(_) |
-                    ast::MacImplItem(_) => {
+                    _ => {
                         panic!("impl method FnLikeNode that is not fn-like")
                     }
                 }
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 2a9a609ecd1..795391d4009 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -940,6 +940,12 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         }
         Some(NodeImplItem(ii)) => {
             match ii.node {
+                ConstImplItem(..) => {
+                    format!("assoc const {} in {}{}",
+                            token::get_ident(ii.ident),
+                            map.path_to_string(id),
+                            id_str)
+                }
                 MethodImplItem(..) => {
                     format!("method {} in {}{}",
                             token::get_ident(ii.ident),
@@ -959,9 +965,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",
-//                 ConstTraitItem(..) => "assoc constant"
             };
 
             format!("{} {} in {}{}",
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8ba36cefc65..22bc3a198e2 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -973,6 +973,10 @@ pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>, folder: &mut T)
         ident: folder.fold_ident(ident),
         attrs: fold_attrs(attrs, folder),
         node: match node {
+            ConstTraitItem(ty, default) => {
+                ConstTraitItem(folder.fold_ty(ty),
+                               default.map(|x| folder.fold_expr(x)))
+            }
             MethodTraitItem(sig, body) => {
                 MethodTraitItem(noop_fold_method_sig(sig, folder),
                                 body.map(|x| folder.fold_block(x)))
@@ -994,6 +998,9 @@ pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T)
         attrs: fold_attrs(attrs, folder),
         vis: vis,
         node: match node  {
+            ConstImplItem(ty, expr) => {
+                ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr))
+            }
             MethodImplItem(sig, body) => {
                 MethodImplItem(noop_fold_method_sig(sig, folder),
                                folder.fold_block(body))
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 5a57e09fcff..6fd2a8b1815 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1269,6 +1269,7 @@ impl<'a> State<'a> {
         try!(self.maybe_print_comment(ti.span.lo));
         try!(self.print_outer_attributes(&ti.attrs));
         match ti.node {
+            ast::ConstTraitItem(_, _) => Ok(()),
             ast::MethodTraitItem(ref sig, ref body) => {
                 if body.is_some() {
                     try!(self.head(""));
@@ -1295,6 +1296,7 @@ impl<'a> State<'a> {
         try!(self.maybe_print_comment(ii.span.lo));
         try!(self.print_outer_attributes(&ii.attrs));
         match ii.node {
+            ast::ConstImplItem(_, _) => Ok(()),
             ast::MethodImplItem(ref sig, ref body) => {
                 try!(self.head(""));
                 try!(self.print_method_sig(ii.ident, sig, ii.vis));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 4c70fc9f81f..2ab35367625 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -619,6 +619,12 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
         visitor.visit_attribute(attr);
     }
     match trait_item.node {
+        ConstTraitItem(ref ty, ref default) => {
+            visitor.visit_ty(ty);
+            if let Some(ref expr) = *default {
+                visitor.visit_expr(expr);
+            }
+        }
         MethodTraitItem(ref sig, None) => {
             visitor.visit_explicit_self(&sig.explicit_self);
             visitor.visit_generics(&sig.generics);
@@ -641,6 +647,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
         visitor.visit_attribute(attr);
     }
     match impl_item.node {
+        ConstImplItem(ref ty, ref expr) => {
+            visitor.visit_ty(ty);
+            visitor.visit_expr(expr);
+        }
         MethodImplItem(ref sig, ref body) => {
             visitor.visit_fn(FkMethod(impl_item.ident, sig, Some(impl_item.vis)), &sig.decl,
                              body, impl_item.span, impl_item.id);