about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2018-05-17 21:28:50 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2018-05-19 20:34:42 +0300
commit26aad254875464ff352a4e18d16f668b5bd9b7cb (patch)
tree82c41e684745a322d3a33156dd00016136a5ce45
parent072b0f617fdd2ccb3bc6dd08718acf9504b7ed3a (diff)
downloadrust-26aad254875464ff352a4e18d16f668b5bd9b7cb.tar.gz
rust-26aad254875464ff352a4e18d16f668b5bd9b7cb.zip
rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants".
-rw-r--r--src/librustc/hir/intravisit.rs22
-rw-r--r--src/librustc/hir/lowering.rs23
-rw-r--r--src/librustc/hir/map/collector.rs9
-rw-r--r--src/librustc/hir/map/def_collector.rs102
-rw-r--r--src/librustc/hir/map/definitions.rs19
-rw-r--r--src/librustc/hir/map/mod.rs47
-rw-r--r--src/librustc/hir/mod.rs20
-rw-r--r--src/librustc/hir/print.rs21
-rw-r--r--src/librustc/ich/impls_hir.rs6
-rw-r--r--src/librustc/ty/item_path.rs3
-rw-r--r--src/librustc/util/ppaux.rs3
-rw-r--r--src/librustc_metadata/encoder.rs16
-rw-r--r--src/librustc_mir/build/mod.rs41
-rw-r--r--src/librustc_mir/hair/cx/expr.rs8
-rw-r--r--src/librustc_resolve/lib.rs36
-rw-r--r--src/librustc_resolve/macros.rs13
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs4
-rw-r--r--src/librustc_save_analysis/sig.rs2
-rw-r--r--src/librustc_typeck/astconv.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs27
-rw-r--r--src/librustc_typeck/collect.rs24
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/libsyntax/ast.rs24
-rw-r--r--src/libsyntax/diagnostics/plugin.rs5
-rw-r--r--src/libsyntax/fold.rs22
-rw-r--r--src/libsyntax/parse/parser.rs24
-rw-r--r--src/libsyntax/print/pprust.rs12
-rw-r--r--src/libsyntax/visit.rs15
-rw-r--r--src/test/compile-fail/issue-48838.rs15
-rw-r--r--src/test/compile-fail/issue-50600.rs15
-rw-r--r--src/test/compile-fail/issue-50688.rs13
-rw-r--r--src/test/run-pass/issue-50689.rs17
-rw-r--r--src/test/ui/issue-23302-1.stderr6
-rw-r--r--src/test/ui/issue-23302-2.stderr6
-rw-r--r--src/test/ui/issue-36163.stderr6
35 files changed, 334 insertions, 306 deletions
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 59b058e9861..2ef022cecdf 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -272,6 +272,9 @@ pub trait Visitor<'v> : Sized {
     fn visit_decl(&mut self, d: &'v Decl) {
         walk_decl(self, d)
     }
+    fn visit_anon_const(&mut self, c: &'v AnonConst) {
+        walk_anon_const(self, c)
+    }
     fn visit_expr(&mut self, ex: &'v Expr) {
         walk_expr(self, ex)
     }
@@ -547,7 +550,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                generics,
                                parent_item_id,
                                variant.span);
-    walk_list!(visitor, visit_nested_body, variant.node.disr_expr);
+    walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
@@ -576,9 +579,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
         TyPath(ref qpath) => {
             visitor.visit_qpath(qpath, typ.id, typ.span);
         }
-        TyArray(ref ty, length) => {
+        TyArray(ref ty, ref length) => {
             visitor.visit_ty(ty);
-            visitor.visit_nested_body(length)
+            visitor.visit_anon_const(length)
         }
         TyTraitObject(ref bounds, ref lifetime) => {
             for bound in bounds {
@@ -592,8 +595,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_lifetime, lifetimes);
         }
-        TyTypeof(expression) => {
-            visitor.visit_nested_body(expression)
+        TyTypeof(ref expression) => {
+            visitor.visit_anon_const(expression)
         }
         TyInfer | TyErr => {}
     }
@@ -944,6 +947,11 @@ pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
     }
 }
 
+pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
+    visitor.visit_id(constant.id);
+    visitor.visit_nested_body(constant.body);
+}
+
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
     visitor.visit_id(expression.id);
     walk_list!(visitor, visit_attribute, expression.attrs.iter());
@@ -954,9 +962,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprArray(ref subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
-        ExprRepeat(ref element, count) => {
+        ExprRepeat(ref element, ref count) => {
             visitor.visit_expr(element);
-            visitor.visit_nested_body(count)
+            visitor.visit_anon_const(count)
         }
         ExprStruct(ref qpath, ref fields, ref optional_base) => {
             visitor.visit_qpath(qpath, expression.id, expression.span);
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 45d429612a1..02c2aa1c71b 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1080,12 +1080,10 @@ impl<'a> LoweringContext<'a> {
                 }),
             )),
             TyKind::Array(ref ty, ref length) => {
-                let length = self.lower_body(None, |this| this.lower_expr(length));
-                hir::TyArray(self.lower_ty(ty, itctx), length)
+                hir::TyArray(self.lower_ty(ty, itctx), self.lower_anon_const(length))
             }
             TyKind::Typeof(ref expr) => {
-                let expr = self.lower_body(None, |this| this.lower_expr(expr));
-                hir::TyTypeof(expr)
+                hir::TyTypeof(self.lower_anon_const(expr))
             }
             TyKind::TraitObject(ref bounds, kind) => {
                 let mut lifetime_bound = None;
@@ -1365,10 +1363,7 @@ impl<'a> LoweringContext<'a> {
                 name: v.node.ident.name,
                 attrs: self.lower_attrs(&v.node.attrs),
                 data: self.lower_variant_data(&v.node.data),
-                disr_expr: v.node
-                    .disr_expr
-                    .as_ref()
-                    .map(|e| self.lower_body(None, |this| this.lower_expr(e))),
+                disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
             },
             span: v.span,
         }
@@ -2927,6 +2922,16 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
+    fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
+        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id);
+
+        hir::AnonConst {
+            id: node_id,
+            hir_id,
+            body: self.lower_body(None, |this| this.lower_expr(&c.value)),
+        }
+    }
+
     fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
         let kind = match e.node {
             ExprKind::Box(ref inner) => hir::ExprBox(P(self.lower_expr(inner))),
@@ -2936,7 +2941,7 @@ impl<'a> LoweringContext<'a> {
             }
             ExprKind::Repeat(ref expr, ref count) => {
                 let expr = P(self.lower_expr(expr));
-                let count = self.lower_body(None, |this| this.lower_expr(count));
+                let count = self.lower_anon_const(count);
                 hir::ExprRepeat(expr, count)
             }
             ExprKind::Tup(ref elts) => {
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 38de8548f30..8f28dfab1e7 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -202,6 +202,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
             NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
             NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
             NodeField(n) => EntryField(parent, dep_node_index, n),
+            NodeAnonConst(n) => EntryAnonConst(parent, dep_node_index, n),
             NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
             NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
             NodeTy(n) => EntryTy(parent, dep_node_index, n),
@@ -390,6 +391,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
+    fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
+        self.insert(constant.id, NodeAnonConst(constant));
+
+        self.with_parent(constant.id, |this| {
+            intravisit::walk_anon_const(this, constant);
+        });
+    }
+
     fn visit_expr(&mut self, expr: &'hir Expr) {
         self.insert(expr.id, NodeExpr(expr));
 
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 810fa04fac4..03b6dc1676f 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -33,7 +33,6 @@ pub struct DefCollector<'a> {
 pub struct MacroInvocationData {
     pub mark: Mark,
     pub def_index: DefIndex,
-    pub const_expr: bool,
 }
 
 impl<'a> DefCollector<'a> {
@@ -74,25 +73,10 @@ impl<'a> DefCollector<'a> {
         self.parent_def = parent;
     }
 
-    pub fn visit_const_expr(&mut self, expr: &Expr) {
-        match expr.node {
-            // Find the node which will be used after lowering.
-            ExprKind::Paren(ref inner) => return self.visit_const_expr(inner),
-            ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, true),
-            // FIXME(eddyb) Closures should have separate
-            // function definition IDs and expression IDs.
-            ExprKind::Closure(..) => return,
-            _ => {}
-        }
-
-        self.create_def(expr.id, DefPathData::Initializer, REGULAR_SPACE, expr.span);
-    }
-
-    fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
+    fn visit_macro_invoc(&mut self, id: NodeId) {
         if let Some(ref mut visit) = self.visit_macro_invoc {
             visit(MacroInvocationData {
                 mark: id.placeholder_to_mark(),
-                const_expr,
                 def_index: self.parent_def.unwrap(),
             })
         }
@@ -119,7 +103,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
                 DefPathData::ValueNs(i.ident.name.as_interned_str()),
             ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_interned_str()),
-            ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
+            ItemKind::Mac(..) => return self.visit_macro_invoc(i.id),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
                 return visit::walk_item(self, i);
@@ -129,30 +113,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
         self.with_parent(def, |this| {
             match i.node {
-                ItemKind::Enum(ref enum_definition, _) => {
-                    for v in &enum_definition.variants {
-                        let variant_def_index =
-                            this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.ident
-                                                                      .name.as_interned_str()),
-                                            REGULAR_SPACE,
-                                            v.span);
-                        this.with_parent(variant_def_index, |this| {
-                            for (index, field) in v.node.data.fields().iter().enumerate() {
-                                let name = field.ident.map(|ident| ident.name)
-                                    .unwrap_or_else(|| Symbol::intern(&index.to_string()));
-                                this.create_def(field.id,
-                                                DefPathData::Field(name.as_interned_str()),
-                                                REGULAR_SPACE,
-                                                field.span);
-                            }
-
-                            if let Some(ref expr) = v.node.disr_expr {
-                                this.visit_const_expr(expr);
-                            }
-                        });
-                    }
-                }
                 ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
                     // If this is a tuple-like struct, register the constructor.
                     if !struct_def.is_struct() {
@@ -161,15 +121,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                                         REGULAR_SPACE,
                                         i.span);
                     }
-
-                    for (index, field) in struct_def.fields().iter().enumerate() {
-                        let name = field.ident.map(|ident| ident.name)
-                            .unwrap_or_else(|| Symbol::intern(&index.to_string()));
-                        this.create_def(field.id,
-                                        DefPathData::Field(name.as_interned_str()),
-                                        REGULAR_SPACE,
-                                        field.span);
-                    }
                 }
                 _ => {}
             }
@@ -184,7 +135,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
         if let ForeignItemKind::Macro(_) = foreign_item.node {
-            return self.visit_macro_invoc(foreign_item.id, false);
+            return self.visit_macro_invoc(foreign_item.id);
         }
 
         let def = self.create_def(foreign_item.id,
@@ -197,6 +148,28 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         });
     }
 
+    fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
+        let def = self.create_def(v.node.data.id(),
+                                  DefPathData::EnumVariant(v.node.ident
+                                                            .name.as_interned_str()),
+                                  REGULAR_SPACE,
+                                  v.span);
+        self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id));
+    }
+
+    fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,
+                          _: &'a Generics, _: NodeId, _: Span) {
+        for (index, field) in data.fields().iter().enumerate() {
+            let name = field.ident.map(|ident| ident.name)
+                .unwrap_or_else(|| Symbol::intern(&index.to_string()));
+            let def = self.create_def(field.id,
+                                      DefPathData::Field(name.as_interned_str()),
+                                      REGULAR_SPACE,
+                                      field.span);
+            self.with_parent(def, |this| this.visit_struct_field(field));
+        }
+    }
+
     fn visit_generic_param(&mut self, param: &'a GenericParam) {
         match *param {
             GenericParam::Lifetime(ref lifetime_def) => {
@@ -227,7 +200,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             TraitItemKind::Type(..) => {
                 DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str())
             },
-            TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
+            TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
         };
 
         let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE, ti.span);
@@ -239,7 +212,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
                 DefPathData::ValueNs(ii.ident.name.as_interned_str()),
             ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
-            ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
+            ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
         };
 
         let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE, ii.span);
@@ -248,17 +221,24 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_pat(&mut self, pat: &'a Pat) {
         match pat.node {
-            PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
+            PatKind::Mac(..) => return self.visit_macro_invoc(pat.id),
             _ => visit::walk_pat(self, pat),
         }
     }
 
+    fn visit_anon_const(&mut self, constant: &'a AnonConst) {
+        let def = self.create_def(constant.id,
+                                  DefPathData::AnonConst,
+                                  REGULAR_SPACE,
+                                  constant.value.span);
+        self.with_parent(def, |this| visit::walk_anon_const(this, constant));
+    }
+
     fn visit_expr(&mut self, expr: &'a Expr) {
         let parent_def = self.parent_def;
 
         match expr.node {
-            ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
-            ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
+            ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
             ExprKind::Closure(..) => {
                 let def = self.create_def(expr.id,
                                           DefPathData::ClosureExpr,
@@ -275,12 +255,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_ty(&mut self, ty: &'a Ty) {
         match ty.node {
-            TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false),
-            TyKind::Array(_, ref length) => self.visit_const_expr(length),
+            TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
             TyKind::ImplTrait(..) => {
                 self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span);
             }
-            TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
             _ => {}
         }
         visit::walk_ty(self, ty);
@@ -288,7 +266,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_stmt(&mut self, stmt: &'a Stmt) {
         match stmt.node {
-            StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false),
+            StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id),
             _ => visit::walk_stmt(self, stmt),
         }
     }
@@ -298,7 +276,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             match nt.0 {
                 token::NtExpr(ref expr) => {
                     if let ExprKind::Mac(..) = expr.node {
-                        self.visit_macro_invoc(expr.id, false);
+                        self.visit_macro_invoc(expr.id);
                     }
                 }
                 _ => {}
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 616dc22486d..e380a7bfbfe 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -231,9 +231,8 @@ impl DefKey {
             DefPathData::Misc |
             DefPathData::ClosureExpr |
             DefPathData::StructCtor |
-            DefPathData::Initializer |
-            DefPathData::ImplTrait |
-            DefPathData::Typeof => {}
+            DefPathData::AnonConst |
+            DefPathData::ImplTrait => {}
         };
 
         disambiguator.hash(&mut hasher);
@@ -389,12 +388,10 @@ pub enum DefPathData {
     Field(InternedString),
     /// Implicit ctor for a tuple-like struct
     StructCtor,
-    /// Initializer for a const
-    Initializer,
+    /// A constant expression (see {ast,hir}::AnonConst).
+    AnonConst,
     /// An `impl Trait` type node.
     ImplTrait,
-    /// A `typeof` type node.
-    Typeof,
 
     /// GlobalMetaData identifies a piece of crate metadata that is global to
     /// a whole crate (as opposed to just one item). GlobalMetaData components
@@ -665,9 +662,8 @@ impl DefPathData {
             Misc |
             ClosureExpr |
             StructCtor |
-            Initializer |
-            ImplTrait |
-            Typeof => None
+            AnonConst |
+            ImplTrait => None
         }
     }
 
@@ -696,9 +692,8 @@ impl DefPathData {
             Misc => "{{?}}",
             ClosureExpr => "{{closure}}",
             StructCtor => "{{constructor}}",
-            Initializer => "{{initializer}}",
+            AnonConst => "{{constant}}",
             ImplTrait => "{{impl-Trait}}",
-            Typeof => "{{typeof}}",
         };
 
         Symbol::intern(s).as_interned_str()
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index a9613a60a57..951bb6ad150 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -53,6 +53,7 @@ pub enum Node<'hir> {
     NodeImplItem(&'hir ImplItem),
     NodeVariant(&'hir Variant),
     NodeField(&'hir StructField),
+    NodeAnonConst(&'hir AnonConst),
     NodeExpr(&'hir Expr),
     NodeStmt(&'hir Stmt),
     NodeTy(&'hir Ty),
@@ -85,6 +86,7 @@ enum MapEntry<'hir> {
     EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem),
     EntryVariant(NodeId, DepNodeIndex, &'hir Variant),
     EntryField(NodeId, DepNodeIndex, &'hir StructField),
+    EntryAnonConst(NodeId, DepNodeIndex, &'hir AnonConst),
     EntryExpr(NodeId, DepNodeIndex, &'hir Expr),
     EntryStmt(NodeId, DepNodeIndex, &'hir Stmt),
     EntryTy(NodeId, DepNodeIndex, &'hir Ty),
@@ -120,6 +122,7 @@ impl<'hir> MapEntry<'hir> {
             EntryImplItem(id, _, _) => id,
             EntryVariant(id, _, _) => id,
             EntryField(id, _, _) => id,
+            EntryAnonConst(id, _, _) => id,
             EntryExpr(id, _, _) => id,
             EntryStmt(id, _, _) => id,
             EntryTy(id, _, _) => id,
@@ -147,6 +150,7 @@ impl<'hir> MapEntry<'hir> {
             EntryImplItem(_, _, n) => NodeImplItem(n),
             EntryVariant(_, _, n) => NodeVariant(n),
             EntryField(_, _, n) => NodeField(n),
+            EntryAnonConst(_, _, n) => NodeAnonConst(n),
             EntryExpr(_, _, n) => NodeExpr(n),
             EntryStmt(_, _, n) => NodeStmt(n),
             EntryTy(_, _, n) => NodeTy(n),
@@ -193,6 +197,8 @@ impl<'hir> MapEntry<'hir> {
                 }
             }
 
+            EntryAnonConst(_, _, constant) => Some(constant.body),
+
             EntryExpr(_, _, expr) => {
                 match expr.node {
                     ExprClosure(.., body, _, _) => Some(body),
@@ -290,6 +296,7 @@ impl<'hir> Map<'hir> {
             EntryLifetime(_, dep_node_index, _) |
             EntryTyParam(_, dep_node_index, _) |
             EntryVisibility(_, dep_node_index, _) |
+            EntryAnonConst(_, dep_node_index, _) |
             EntryExpr(_, dep_node_index, _) |
             EntryLocal(_, dep_node_index, _) |
             EntryMacroDef(dep_node_index, _) |
@@ -434,6 +441,7 @@ impl<'hir> Map<'hir> {
                 Some(Def::Variant(def_id))
             }
             NodeField(_) |
+            NodeAnonConst(_) |
             NodeExpr(_) |
             NodeStmt(_) |
             NodeTy(_) |
@@ -495,15 +503,11 @@ impl<'hir> Map<'hir> {
 
     /// Returns the `NodeId` that corresponds to the definition of
     /// which this is the body of, i.e. a `fn`, `const` or `static`
-    /// item (possibly associated), or a closure, or the body itself
-    /// for embedded constant expressions (e.g. `N` in `[T; N]`).
+    /// item (possibly associated), a closure, or a `hir::AnonConst`.
     pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
         let parent = self.get_parent_node(node_id);
-        if self.map[parent.as_usize()].is_body_owner(node_id) {
-            parent
-        } else {
-            node_id
-        }
+        assert!(self.map[parent.as_usize()].is_body_owner(node_id));
+        parent
     }
 
     pub fn body_owner_def_id(&self, id: BodyId) -> DefId {
@@ -520,19 +524,7 @@ impl<'hir> Map<'hir> {
                 self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
             }
 
-            if let Some(body_id) = entry.associated_body() {
-                // For item-like things and closures, the associated
-                // body has its own distinct id, and that is returned
-                // by `associated_body`.
-                Some(body_id)
-            } else {
-                // For some expressions, the expression is its own body.
-                if let EntryExpr(_, _, expr) = entry {
-                    Some(BodyId { node_id: expr.id })
-                } else {
-                    None
-                }
-            }
+            entry.associated_body()
         } else {
             bug!("no entry for id `{}`", id)
         }
@@ -547,17 +539,11 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
-        // Handle constants in enum discriminants, types, and repeat expressions.
-        let def_id = self.local_def_id(id);
-        let def_key = self.def_key(def_id);
-        if def_key.disambiguated_data.data == DefPathData::Initializer {
-            return BodyOwnerKind::Const;
-        }
-
         match self.get(id) {
             NodeItem(&Item { node: ItemConst(..), .. }) |
             NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
-            NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
+            NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) |
+            NodeAnonConst(_) => {
                 BodyOwnerKind::Const
             }
             NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => {
@@ -982,6 +968,7 @@ impl<'hir> Map<'hir> {
             Some(EntryImplItem(_, _, impl_item)) => impl_item.span,
             Some(EntryVariant(_, _, variant)) => variant.span,
             Some(EntryField(_, _, field)) => field.span,
+            Some(EntryAnonConst(_, _, constant)) => self.body(constant.body).value.span,
             Some(EntryExpr(_, _, expr)) => expr.span,
             Some(EntryStmt(_, _, stmt)) => stmt.span,
             Some(EntryTy(_, _, ty)) => ty.span,
@@ -1201,6 +1188,7 @@ impl<'a> print::State<'a> {
             NodeTraitItem(a)   => self.print_trait_item(a),
             NodeImplItem(a)    => self.print_impl_item(a),
             NodeVariant(a)     => self.print_variant(&a),
+            NodeAnonConst(a)   => self.print_anon_const(&a),
             NodeExpr(a)        => self.print_expr(&a),
             NodeStmt(a)        => self.print_stmt(&a),
             NodeTy(a)          => self.print_type(&a),
@@ -1306,6 +1294,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                     field.name,
                     path_str(), id_str)
         }
+        Some(NodeAnonConst(_)) => {
+            format!("const {}{}", map.node_to_pretty_string(id), id_str)
+        }
         Some(NodeExpr(_)) => {
             format!("expr {}{}", map.node_to_pretty_string(id), id_str)
         }
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index edd5e668d5e..caae79961a6 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1272,6 +1272,18 @@ pub enum BodyOwnerKind {
     Static(Mutability),
 }
 
+/// A constant (expression) that's not an item or associated item,
+/// but needs its own `DefId` for type-checking, const-eval, etc.
+/// These are usually found nested inside types (e.g. array lengths)
+/// or expressions (e.g. repeat counts), and also used to define
+/// explicit discriminant values for enum variants.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct AnonConst {
+    pub id: NodeId,
+    pub hir_id: HirId,
+    pub body: BodyId,
+}
+
 /// An expression
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Expr {
@@ -1419,7 +1431,7 @@ pub enum Expr_ {
     ///
     /// For example, `[1; 5]`. The first expression is the element
     /// to be repeated; the second is the number of times to repeat it.
-    ExprRepeat(P<Expr>, BodyId),
+    ExprRepeat(P<Expr>, AnonConst),
 
     /// A suspension point for generators. This is `yield <expr>` in Rust.
     ExprYield(P<Expr>),
@@ -1677,7 +1689,7 @@ pub enum Ty_ {
     /// A variable length slice (`[T]`)
     TySlice(P<Ty>),
     /// A fixed length array (`[T; n]`)
-    TyArray(P<Ty>, BodyId),
+    TyArray(P<Ty>, AnonConst),
     /// A raw pointer (`*const T` or `*mut T`)
     TyPtr(MutTy),
     /// A reference (`&'a T` or `&'a mut T`)
@@ -1709,7 +1721,7 @@ pub enum Ty_ {
     /// so they are resolved directly through the parent `Generics`.
     TyImplTraitExistential(ExistTy, HirVec<Lifetime>),
     /// Unused for now
-    TyTypeof(BodyId),
+    TyTypeof(AnonConst),
     /// TyInfer means the type should be inferred instead of it having been
     /// specified. This can appear anywhere in a type.
     TyInfer,
@@ -1882,7 +1894,7 @@ pub struct Variant_ {
     pub attrs: HirVec<Attribute>,
     pub data: VariantData,
     /// Explicit discriminant, eg `Foo = 1`
-    pub disr_expr: Option<BodyId>,
+    pub disr_expr: Option<AnonConst>,
 }
 
 pub type Variant = Spanned<Variant_>;
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index 940a68e8ce5..8173ec48045 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -416,16 +416,16 @@ impl<'a> State<'a> {
             hir::TyImplTraitExistential(ref existty, ref _lifetimes) => {
                 self.print_bounds("impl", &existty.bounds[..])?;
             }
-            hir::TyArray(ref ty, v) => {
+            hir::TyArray(ref ty, ref length) => {
                 self.s.word("[")?;
                 self.print_type(&ty)?;
                 self.s.word("; ")?;
-                self.ann.nested(self, Nested::Body(v))?;
+                self.print_anon_const(length)?;
                 self.s.word("]")?;
             }
-            hir::TyTypeof(e) => {
+            hir::TyTypeof(ref e) => {
                 self.s.word("typeof(")?;
-                self.ann.nested(self, Nested::Body(e))?;
+                self.print_anon_const(e)?;
                 self.s.word(")")?;
             }
             hir::TyInfer => {
@@ -871,10 +871,10 @@ impl<'a> State<'a> {
         self.head("")?;
         let generics = hir::Generics::empty();
         self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
-        if let Some(d) = v.node.disr_expr {
+        if let Some(ref d) = v.node.disr_expr {
             self.s.space()?;
             self.word_space("=")?;
-            self.ann.nested(self, Nested::Body(d))?;
+            self.print_anon_const(d)?;
         }
         Ok(())
     }
@@ -1091,6 +1091,9 @@ impl<'a> State<'a> {
         self.print_else(elseopt)
     }
 
+    pub fn print_anon_const(&mut self, constant: &hir::AnonConst) -> io::Result<()> {
+        self.ann.nested(self, Nested::Body(constant.body))
+    }
 
     fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
         self.popen()?;
@@ -1141,12 +1144,12 @@ impl<'a> State<'a> {
         self.end()
     }
 
-    fn print_expr_repeat(&mut self, element: &hir::Expr, count: hir::BodyId) -> io::Result<()> {
+    fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::AnonConst) -> io::Result<()> {
         self.ibox(indent_unit)?;
         self.s.word("[")?;
         self.print_expr(element)?;
         self.word_space(";")?;
-        self.ann.nested(self, Nested::Body(count))?;
+        self.print_anon_const(count)?;
         self.s.word("]")?;
         self.end()
     }
@@ -1288,7 +1291,7 @@ impl<'a> State<'a> {
             hir::ExprArray(ref exprs) => {
                 self.print_expr_vec(exprs)?;
             }
-            hir::ExprRepeat(ref element, count) => {
+            hir::ExprRepeat(ref element, ref count) => {
                 self.print_expr_repeat(&element, count)?;
             }
             hir::ExprStruct(ref qpath, ref fields, ref wth) => {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 30f725a6b50..21c1af919de 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -553,6 +553,12 @@ impl_stable_hash_for!(enum hir::UnsafeSource {
     UserProvided
 });
 
+impl_stable_hash_for!(struct hir::AnonConst {
+    id,
+    hir_id,
+    body
+});
+
 impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 41625afec86..93d78210b1a 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -214,11 +214,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             data @ DefPathData::LifetimeDef(..) |
             data @ DefPathData::EnumVariant(..) |
             data @ DefPathData::Field(..) |
-            data @ DefPathData::Initializer |
+            data @ DefPathData::AnonConst |
             data @ DefPathData::MacroDef(..) |
             data @ DefPathData::ClosureExpr |
             data @ DefPathData::ImplTrait |
-            data @ DefPathData::Typeof |
             data @ DefPathData::GlobalMetaData(..) => {
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
                 self.push_item_path(buffer, parent_def_id);
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index c66dd79cbf5..b8345b6c2d9 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -290,9 +290,8 @@ impl PrintContext {
                     DefPathData::LifetimeDef(_) |
                     DefPathData::Field(_) |
                     DefPathData::StructCtor |
-                    DefPathData::Initializer |
+                    DefPathData::AnonConst |
                     DefPathData::ImplTrait |
-                    DefPathData::Typeof |
                     DefPathData::GlobalMetaData(_) => {
                         // if we're making a symbol for something, there ought
                         // to be a value or type-def or something in there
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index d00f4f32c10..a8836694933 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1359,8 +1359,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         }
     }
 
-    fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id);
+    fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> {
+        debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id);
         let tcx = self.tcx;
         let id = tcx.hir.as_local_node_id(def_id).unwrap();
         let body_id = tcx.hir.body_owned_by(id);
@@ -1623,9 +1623,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
                      id: ast::NodeId) {
         intravisit::walk_variant(self, v, g, id);
 
-        if let Some(discr) = v.node.disr_expr {
-            let def_id = self.index.tcx.hir.body_owner_def_id(discr);
-            self.index.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id);
+        if let Some(ref discr) = v.node.disr_expr {
+            let def_id = self.index.tcx.hir.local_def_id(discr.id);
+            self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
         }
     }
     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
@@ -1668,9 +1668,9 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
                 let def_id = self.tcx.hir.local_def_id(ty.id);
                 self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
             }
-            hir::TyArray(_, len) => {
-                let def_id = self.tcx.hir.body_owner_def_id(len);
-                self.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id);
+            hir::TyArray(_, ref length) => {
+                let def_id = self.tcx.hir.local_def_id(length.id);
+                self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
             }
             _ => {}
         }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 3bbf73ec8b5..2da2d3f697f 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -42,46 +42,15 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
 
     // Figure out what primary body this item has.
     let body_id = match tcx.hir.get(id) {
-        hir::map::NodeItem(item) => {
-            match item.node {
-                hir::ItemConst(_, body) |
-                hir::ItemStatic(_, _, body) |
-                hir::ItemFn(.., body) => body,
-                _ => unsupported()
-            }
-        }
-        hir::map::NodeTraitItem(item) => {
-            match item.node {
-                hir::TraitItemKind::Const(_, Some(body)) |
-                hir::TraitItemKind::Method(_,
-                    hir::TraitMethod::Provided(body)) => body,
-                _ => unsupported()
-            }
-        }
-        hir::map::NodeImplItem(item) => {
-            match item.node {
-                hir::ImplItemKind::Const(_, body) |
-                hir::ImplItemKind::Method(_, body) => body,
-                _ => unsupported()
-            }
-        }
-        hir::map::NodeExpr(expr) => {
-            // FIXME(eddyb) Closures should have separate
-            // function definition IDs and expression IDs.
-            // Type-checking should not let closures get
-            // this far in a constant position.
-            // Assume that everything other than closures
-            // is a constant "initializer" expression.
-            match expr.node {
-                hir::ExprClosure(_, _, body, _, _) => body,
-                _ => hir::BodyId { node_id: expr.id },
-            }
-        }
         hir::map::NodeVariant(variant) =>
             return create_constructor_shim(tcx, id, &variant.node.data),
         hir::map::NodeStructCtor(ctor) =>
             return create_constructor_shim(tcx, id, ctor),
-        _ => unsupported(),
+
+        _ => match tcx.hir.maybe_body_owned_by(id) {
+            Some(body) => body,
+            None => unsupported(),
+        },
     };
 
     tcx.infer_ctxt().enter(|infcx| {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 97a4e0f3724..0d93634981f 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -506,9 +506,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         // Now comes the rote stuff:
-        hir::ExprRepeat(ref v, count) => {
-            let c = &cx.tcx.hir.body(count).value;
-            let def_id = cx.tcx.hir.body_owner_def_id(count);
+        hir::ExprRepeat(ref v, ref count) => {
+            let def_id = cx.tcx.hir.local_def_id(count.id);
             let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
             let instance = ty::Instance::resolve(
                 cx.tcx.global_tcx(),
@@ -520,7 +519,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 instance,
                 promoted: None
             };
-            let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and(global_id)) {
+            let span = cx.tcx.def_span(def_id);
+            let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) {
                 Ok(cv) => cv.unwrap_usize(cx.tcx),
                 Err(e) => {
                     e.report(cx.tcx, cx.tcx.def_span(def_id), "array length");
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index e13e6bc6b74..a8ac940765d 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -802,6 +802,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
     fn visit_block(&mut self, block: &'tcx Block) {
         self.resolve_block(block);
     }
+    fn visit_anon_const(&mut self, constant: &'tcx ast::AnonConst) {
+        self.with_constant_rib(|this| {
+            visit::walk_anon_const(this, constant);
+        });
+    }
     fn visit_expr(&mut self, expr: &'tcx Expr) {
         self.resolve_expr(expr, None);
     }
@@ -819,13 +824,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                               .map_or(Def::Err, |d| d.def());
                 self.record_def(ty.id, PathResolution::new(def));
             }
-            TyKind::Array(ref element, ref length) => {
-                self.visit_ty(element);
-                self.with_constant_rib(|this| {
-                    this.visit_expr(length);
-                });
-                return;
-            }
             _ => (),
         }
         visit::walk_ty(self, ty);
@@ -837,24 +835,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
                                 &tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe));
         visit::walk_poly_trait_ref(self, tref, m);
     }
-    fn visit_variant(&mut self,
-                     variant: &'tcx ast::Variant,
-                     generics: &'tcx Generics,
-                     item_id: ast::NodeId) {
-        if let Some(ref dis_expr) = variant.node.disr_expr {
-            // resolve the discriminator expr as a constant
-            self.with_constant_rib(|this| {
-                this.visit_expr(dis_expr);
-            });
-        }
-
-        // `visit::walk_variant` without the discriminant expression.
-        self.visit_variant_data(&variant.node.data,
-                                variant.node.ident,
-                                generics,
-                                item_id,
-                                variant.span);
-    }
     fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
         let type_parameters = match foreign_item.node {
             ForeignItemKind::Fn(_, ref generics) => {
@@ -3820,12 +3800,6 @@ impl<'a> Resolver<'a> {
                 self.visit_path_segment(expr.span, segment);
             }
 
-            ExprKind::Repeat(ref element, ref count) => {
-                self.visit_expr(element);
-                self.with_constant_rib(|this| {
-                    this.visit_expr(count);
-                });
-            }
             ExprKind::Call(ref callee, ref arguments) => {
                 self.resolve_expr(callee, Some(expr));
                 for argument in arguments {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 0fc963a1367..296d1a5828a 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -45,9 +45,6 @@ use rustc_data_structures::sync::Lrc;
 pub struct InvocationData<'a> {
     pub module: Cell<Module<'a>>,
     pub def_index: DefIndex,
-    // True if this expansion is in a `const_expr` position, for example `[u32; m!()]`.
-    // c.f. `DefCollector::visit_const_expr`.
-    pub const_expr: bool,
     // The scope in which the invocation path is resolved.
     pub legacy_scope: Cell<LegacyScope<'a>>,
     // The smallest scope that includes this invocation's expansion,
@@ -60,7 +57,6 @@ impl<'a> InvocationData<'a> {
         InvocationData {
             module: Cell::new(graph_root),
             def_index: CRATE_DEF_INDEX,
-            const_expr: false,
             legacy_scope: Cell::new(LegacyScope::Empty),
             expansion: Cell::new(LegacyScope::Empty),
         }
@@ -124,7 +120,6 @@ impl<'a> base::Resolver for Resolver<'a> {
         self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
             module: Cell::new(module),
             def_index: module.def_id().unwrap().index,
-            const_expr: false,
             legacy_scope: Cell::new(LegacyScope::Empty),
             expansion: Cell::new(LegacyScope::Empty),
         }));
@@ -716,13 +711,12 @@ impl<'a> Resolver<'a> {
                        invocation: &'a InvocationData<'a>,
                        expansion: &Expansion) {
         let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
-        let InvocationData { def_index, const_expr, .. } = *invocation;
+        let InvocationData { def_index, .. } = *invocation;
 
         let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
             invocations.entry(invoc.mark).or_insert_with(|| {
                 arenas.alloc_invocation_data(InvocationData {
                     def_index: invoc.def_index,
-                    const_expr: invoc.const_expr,
                     module: Cell::new(graph_root),
                     expansion: Cell::new(LegacyScope::Empty),
                     legacy_scope: Cell::new(LegacyScope::Empty),
@@ -733,11 +727,6 @@ impl<'a> Resolver<'a> {
         let mut def_collector = DefCollector::new(&mut self.definitions, mark);
         def_collector.visit_macro_invoc = Some(visit_macro_invoc);
         def_collector.with_parent(def_index, |def_collector| {
-            if const_expr {
-                if let Expansion::Expr(ref expr) = *expansion {
-                    def_collector.visit_const_expr(expr);
-                }
-            }
             expansion.visit_with(def_collector)
         });
     }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 2ef294fe430..279ee403cc6 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1516,7 +1516,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
             }
             ast::TyKind::Array(ref element, ref length) => {
                 self.visit_ty(element);
-                self.nest_tables(length.id, |v| v.visit_expr(length));
+                self.nest_tables(length.id, |v| v.visit_expr(&length.value));
             }
             _ => visit::walk_ty(self, t),
         }
@@ -1589,7 +1589,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
             }
             ast::ExprKind::Repeat(ref element, ref count) => {
                 self.visit_expr(element);
-                self.nest_tables(count.id, |v| v.visit_expr(count));
+                self.nest_tables(count.id, |v| v.visit_expr(&count.value));
             }
             // In particular, we take this branch for call and path expressions,
             // where we'll index the idents involved just by continuing to walk.
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 829ed320d75..e3545e8f1a9 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -313,7 +313,7 @@ impl Sig for ast::Ty {
             }
             ast::TyKind::Array(ref ty, ref v) => {
                 let nested_ty = ty.make(offset + 1, id, scx)?;
-                let expr = pprust::expr_to_string(v).replace('\n', " ");
+                let expr = pprust::expr_to_string(&v.value).replace('\n', " ");
                 let text = format!("[{}; {}]", nested_ty.text, expr);
                 Ok(replace_text(nested_ty, text))
             }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index c1868467503..e6ccbd61bd5 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1116,8 +1116,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 };
                 self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
             }
-            hir::TyArray(ref ty, length) => {
-                let length_def_id = tcx.hir.body_owner_def_id(length);
+            hir::TyArray(ref ty, ref length) => {
+                let length_def_id = tcx.hir.local_def_id(length.id);
                 let substs = Substs::identity_for_item(tcx, length_def_id);
                 let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize);
                 let array_ty = tcx.mk_ty(ty::TyArray(self.ast_ty_to_ty(&ty), length));
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 39de09fe34f..1088ec1b2ac 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -787,20 +787,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     None,
             }
         }
-        hir::map::NodeExpr(expr) => {
-            // FIXME(eddyb) Closures should have separate
-            // function definition IDs and expression IDs.
-            // Type-checking should not let closures get
-            // this far in a constant position.
-            // Assume that everything other than closures
-            // is a constant "initializer" expression.
-            match expr.node {
-                hir::ExprClosure(..) =>
-                    None,
-                _ =>
-                    Some((hir::BodyId { node_id: expr.id }, None)),
-            }
-        }
+        hir::map::NodeAnonConst(constant) => Some((constant.body, None)),
         _ => None,
     }
 }
@@ -1674,8 +1661,8 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     for v in vs {
-        if let Some(e) = v.node.disr_expr {
-            tcx.typeck_tables_of(tcx.hir.local_def_id(e.node_id));
+        if let Some(ref e) = v.node.disr_expr {
+            tcx.typeck_tables_of(tcx.hir.local_def_id(e.id));
         }
     }
 
@@ -1686,11 +1673,11 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap();
             let variant_i = tcx.hir.expect_variant(variant_i_node_id);
             let i_span = match variant_i.node.disr_expr {
-                Some(expr) => tcx.hir.span(expr.node_id),
+                Some(ref expr) => tcx.hir.span(expr.id),
                 None => tcx.hir.span(variant_i_node_id)
             };
             let span = match v.node.disr_expr {
-                Some(expr) => tcx.hir.span(expr.node_id),
+                Some(ref expr) => tcx.hir.span(expr.id),
                 None => v.span
             };
             struct_span_err!(tcx.sess, span, E0081,
@@ -3975,8 +3962,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
               };
               tcx.mk_array(element_ty, args.len() as u64)
           }
-          hir::ExprRepeat(ref element, count) => {
-            let count_def_id = tcx.hir.body_owner_def_id(count);
+          hir::ExprRepeat(ref element, ref count) => {
+            let count_def_id = tcx.hir.local_def_id(count.id);
             let param_env = ty::ParamEnv::empty();
             let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
             let instance = ty::Instance::resolve(
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 157f3ab76ca..4d691de2037 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -481,8 +481,8 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // fill the discriminant values and field types
     for variant in variants {
         let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
-        prev_discr = Some(if let Some(e) = variant.node.disr_expr {
-            let expr_did = tcx.hir.local_def_id(e.node_id);
+        prev_discr = Some(if let Some(ref e) = variant.node.disr_expr {
+            let expr_did = tcx.hir.local_def_id(e.id);
             def.eval_explicit_discr(tcx, expr_did)
         } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
             Some(discr)
@@ -565,9 +565,9 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let mut distance_from_explicit = 0;
             (AdtKind::Enum, def.variants.iter().map(|v| {
                 let did = tcx.hir.local_def_id(v.node.data.id());
-                let discr = if let Some(e) = v.node.disr_expr {
+                let discr = if let Some(ref e) = v.node.disr_expr {
                     distance_from_explicit = 0;
-                    ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.node_id))
+                    ty::VariantDiscr::Explicit(tcx.hir.local_def_id(e.id))
                 } else {
                     ty::VariantDiscr::Relative(distance_from_explicit)
                 };
@@ -1102,20 +1102,20 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             tcx.mk_closure(def_id, substs)
         }
 
-        NodeExpr(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) {
-            NodeTy(&hir::Ty { node: TyArray(_, body), .. }) |
-            NodeTy(&hir::Ty { node: TyTypeof(body), .. }) |
-            NodeExpr(&hir::Expr { node: ExprRepeat(_, body), .. })
-                if body.node_id == node_id => tcx.types.usize,
+        NodeAnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) {
+            NodeTy(&hir::Ty { node: TyArray(_, ref constant), .. }) |
+            NodeTy(&hir::Ty { node: TyTypeof(ref constant), .. }) |
+            NodeExpr(&hir::Expr { node: ExprRepeat(_, ref constant), .. })
+                if constant.id == node_id => tcx.types.usize,
 
-            NodeVariant(&Spanned { node: Variant_ { disr_expr: Some(e), .. }, .. })
-                if e.node_id == node_id => {
+            NodeVariant(&Spanned { node: Variant_ { disr_expr: Some(ref e), .. }, .. })
+                if e.id == node_id => {
                     tcx.adt_def(tcx.hir.get_parent_did(node_id))
                         .repr.discr_type().to_ty(tcx)
                 }
 
             x => {
-                bug!("unexpected expr parent in type_of_def_id(): {:?}", x);
+                bug!("unexpected const parent in type_of_def_id(): {:?}", x);
             }
         },
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 6beb64dced1..ae53b9ded4e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2669,19 +2669,19 @@ impl Clean<Type> for hir::Ty {
                              type_: box m.ty.clean(cx)}
             }
             TySlice(ref ty) => Slice(box ty.clean(cx)),
-            TyArray(ref ty, n) => {
-                let def_id = cx.tcx.hir.body_owner_def_id(n);
+            TyArray(ref ty, ref length) => {
+                let def_id = cx.tcx.hir.local_def_id(length.id);
                 let param_env = cx.tcx.param_env(def_id);
                 let substs = Substs::identity_for_item(cx.tcx, def_id);
                 let cid = GlobalId {
                     instance: ty::Instance::new(def_id, substs),
                     promoted: None
                 };
-                let n = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| {
+                let length = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| {
                     ty::Const::unevaluated(cx.tcx, def_id, substs, cx.tcx.types.usize)
                 });
-                let n = print_const(cx, n);
-                Array(box ty.clean(cx), n)
+                let length = print_const(cx, length);
+                Array(box ty.clean(cx), length)
             },
             TyTup(ref tys) => Tuple(tys.clean(cx)),
             TyPath(hir::QPath::Resolved(None, ref path)) => {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 1817726d6a1..0ce9763ded8 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -920,6 +920,18 @@ pub enum UnsafeSource {
     UserProvided,
 }
 
+/// A constant (expression) that's not an item or associated item,
+/// but needs its own `DefId` for type-checking, const-eval, etc.
+/// These are usually found nested inside types (e.g. array lengths)
+/// or expressions (e.g. repeat counts), and also used to define
+/// explicit discriminant values for enum variants.
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct AnonConst {
+    pub id: NodeId,
+    pub value: P<Expr>,
+}
+
+
 /// An expression
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)]
 pub struct Expr {
@@ -1168,9 +1180,9 @@ pub enum ExprKind {
 
     /// An array literal constructed from one repeated element.
     ///
-    /// For example, `[1; 5]`. The first expression is the element
-    /// to be repeated; the second is the number of times to repeat it.
-    Repeat(P<Expr>, P<Expr>),
+    /// For example, `[1; 5]`. The expression is the element to be
+    /// repeated; the constant is the number of times to repeat it.
+    Repeat(P<Expr>, AnonConst),
 
     /// No-op: used solely so we can pretty-print faithfully
     Paren(P<Expr>),
@@ -1565,7 +1577,7 @@ pub enum TyKind {
     /// A variable-length slice (`[T]`)
     Slice(P<Ty>),
     /// A fixed length array (`[T; n]`)
-    Array(P<Ty>, P<Expr>),
+    Array(P<Ty>, AnonConst),
     /// A raw pointer (`*const T` or `*mut T`)
     Ptr(MutTy),
     /// A reference (`&'a T` or `&'a mut T`)
@@ -1590,7 +1602,7 @@ pub enum TyKind {
     /// No-op; kept solely so that we can pretty-print faithfully
     Paren(P<Ty>),
     /// Unused for now
-    Typeof(P<Expr>),
+    Typeof(AnonConst),
     /// TyKind::Infer means the type should be inferred instead of it having been
     /// specified. This can appear anywhere in a type.
     Infer,
@@ -1856,7 +1868,7 @@ pub struct Variant_ {
     pub attrs: Vec<Attribute>,
     pub data: VariantData,
     /// Explicit discriminant, e.g. `Foo = 1`
-    pub disr_expr: Option<P<Expr>>,
+    pub disr_expr: Option<AnonConst>,
 }
 
 pub type Variant = Spanned<Variant_>;
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index aecf32ab6af..6c3117b963f 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -207,7 +207,10 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
                 span,
                 ast::TyKind::Tup(vec![ty_str.clone(), ty_str])
             ),
-            ecx.expr_usize(span, count),
+            ast::AnonConst {
+                id: ast::DUMMY_NODE_ID,
+                value: ecx.expr_usize(span, count),
+            },
         ),
     );
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 29cc208c06b..28fb95f165f 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -112,6 +112,10 @@ pub trait Folder : Sized {
         noop_fold_pat(p, self)
     }
 
+    fn fold_anon_const(&mut self, c: AnonConst) -> AnonConst {
+        noop_fold_anon_const(c, self)
+    }
+
     fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
         e.map(|e| noop_fold_expr(e, self))
     }
@@ -394,11 +398,11 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
                 });
                 TyKind::Path(qself, fld.fold_path(path))
             }
-            TyKind::Array(ty, e) => {
-                TyKind::Array(fld.fold_ty(ty), fld.fold_expr(e))
+            TyKind::Array(ty, length) => {
+                TyKind::Array(fld.fold_ty(ty), fld.fold_anon_const(length))
             }
             TyKind::Typeof(expr) => {
-                TyKind::Typeof(fld.fold_expr(expr))
+                TyKind::Typeof(fld.fold_anon_const(expr))
             }
             TyKind::TraitObject(bounds, syntax) => {
                 TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax)
@@ -433,7 +437,7 @@ pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
             ident: fld.fold_ident(v.node.ident),
             attrs: fold_attrs(v.node.attrs, fld),
             data: fld.fold_variant_data(v.node.data),
-            disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)),
+            disr_expr: v.node.disr_expr.map(|e| fld.fold_anon_const(e)),
         },
         span: fld.new_span(v.span),
     }
@@ -1170,6 +1174,14 @@ pub fn noop_fold_range_end<T: Folder>(end: RangeEnd, _folder: &mut T) -> RangeEn
     end
 }
 
+pub fn noop_fold_anon_const<T: Folder>(constant: AnonConst, folder: &mut T) -> AnonConst {
+    let AnonConst {id, value} = constant;
+    AnonConst {
+        id: folder.new_id(id),
+        value: folder.fold_expr(value),
+    }
+}
+
 pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr {
     Expr {
         node: match node {
@@ -1180,7 +1192,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                 ExprKind::Array(folder.fold_exprs(exprs))
             }
             ExprKind::Repeat(expr, count) => {
-                ExprKind::Repeat(folder.fold_expr(expr), folder.fold_expr(count))
+                ExprKind::Repeat(folder.fold_expr(expr), folder.fold_anon_const(count))
             }
             ExprKind::Tup(exprs) => ExprKind::Tup(folder.fold_exprs(exprs)),
             ExprKind::Call(f, args) => {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7b91c491700..aca23581d95 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -12,7 +12,7 @@ use rustc_target::spec::abi::{self, Abi};
 use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy};
 use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::Unsafety;
-use ast::{Mod, Arg, Arm, Attribute, BindingMode, TraitItemKind};
+use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind};
 use ast::Block;
 use ast::{BlockCheckMode, CaptureBy, Movability};
 use ast::{Constness, Crate};
@@ -1543,7 +1543,10 @@ impl<'a> Parser<'a> {
             // Parse optional `; EXPR` in `[TYPE; EXPR]`
             let t = match self.maybe_parse_fixed_length_of_vec()? {
                 None => TyKind::Slice(t),
-                Some(suffix) => TyKind::Array(t, suffix),
+                Some(length) => TyKind::Array(t, AnonConst {
+                    id: ast::DUMMY_NODE_ID,
+                    value: length,
+                }),
             };
             self.expect(&token::CloseDelim(token::Bracket))?;
             t
@@ -1555,7 +1558,10 @@ impl<'a> Parser<'a> {
             // `typeof(EXPR)`
             // In order to not be ambiguous, the type must be surrounded by parens.
             self.expect(&token::OpenDelim(token::Paren))?;
-            let e = self.parse_expr()?;
+            let e = AnonConst {
+                id: ast::DUMMY_NODE_ID,
+                value: self.parse_expr()?,
+            };
             self.expect(&token::CloseDelim(token::Paren))?;
             TyKind::Typeof(e)
         } else if self.eat_keyword(keywords::Underscore) {
@@ -2264,7 +2270,10 @@ impl<'a> Parser<'a> {
                     if self.check(&token::Semi) {
                         // Repeating array syntax: [ 0; 512 ]
                         self.bump();
-                        let count = self.parse_expr()?;
+                        let count = AnonConst {
+                            id: ast::DUMMY_NODE_ID,
+                            value: self.parse_expr()?,
+                        };
                         self.expect(&token::CloseDelim(token::Bracket))?;
                         ex = ExprKind::Repeat(first_expr, count);
                     } else if self.check(&token::Comma) {
@@ -6353,8 +6362,11 @@ impl<'a> Parser<'a> {
                 struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?,
                                                 ast::DUMMY_NODE_ID);
             } else if self.eat(&token::Eq) {
-                disr_expr = Some(self.parse_expr()?);
-                any_disr = disr_expr.as_ref().map(|expr| expr.span);
+                disr_expr = Some(AnonConst {
+                    id: ast::DUMMY_NODE_ID,
+                    value: self.parse_expr()?,
+                });
+                any_disr = disr_expr.as_ref().map(|c| c.value.span);
                 struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
             } else {
                 struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 17f83a09c77..be3408ce565 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1076,16 +1076,16 @@ impl<'a> State<'a> {
             ast::TyKind::ImplTrait(ref bounds) => {
                 self.print_bounds("impl", &bounds[..])?;
             }
-            ast::TyKind::Array(ref ty, ref v) => {
+            ast::TyKind::Array(ref ty, ref length) => {
                 self.s.word("[")?;
                 self.print_type(ty)?;
                 self.s.word("; ")?;
-                self.print_expr(v)?;
+                self.print_expr(&length.value)?;
                 self.s.word("]")?;
             }
             ast::TyKind::Typeof(ref e) => {
                 self.s.word("typeof(")?;
-                self.print_expr(e)?;
+                self.print_expr(&e.value)?;
                 self.s.word(")")?;
             }
             ast::TyKind::Infer => {
@@ -1552,7 +1552,7 @@ impl<'a> State<'a> {
             Some(ref d) => {
                 self.s.space()?;
                 self.word_space("=")?;
-                self.print_expr(d)
+                self.print_expr(&d.value)
             }
             _ => Ok(())
         }
@@ -1905,14 +1905,14 @@ impl<'a> State<'a> {
 
     fn print_expr_repeat(&mut self,
                          element: &ast::Expr,
-                         count: &ast::Expr,
+                         count: &ast::AnonConst,
                          attrs: &[Attribute]) -> io::Result<()> {
         self.ibox(INDENT_UNIT)?;
         self.s.word("[")?;
         self.print_inner_attributes_inline(attrs)?;
         self.print_expr(element)?;
         self.word_space(";")?;
-        self.print_expr(count)?;
+        self.print_expr(&count.value)?;
         self.s.word("]")?;
         self.end()
     }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 2013e838c05..b6eb649daa2 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -69,6 +69,7 @@ pub trait Visitor<'ast>: Sized {
     fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) }
     fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
     fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) }
+    fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) }
     fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
     fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
     fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
@@ -296,7 +297,7 @@ pub fn walk_variant<'a, V>(visitor: &mut V,
     visitor.visit_ident(variant.node.ident);
     visitor.visit_variant_data(&variant.node.data, variant.node.ident,
                              generics, item_id, variant.span);
-    walk_list!(visitor, visit_expr, &variant.node.disr_expr);
+    walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
@@ -326,16 +327,16 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
             }
             visitor.visit_path(path, typ.id);
         }
-        TyKind::Array(ref ty, ref expression) => {
+        TyKind::Array(ref ty, ref length) => {
             visitor.visit_ty(ty);
-            visitor.visit_expr(expression)
+            visitor.visit_anon_const(length)
         }
         TyKind::TraitObject(ref bounds, ..) |
         TyKind::ImplTrait(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         TyKind::Typeof(ref expression) => {
-            visitor.visit_expr(expression)
+            visitor.visit_anon_const(expression)
         }
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
         TyKind::Mac(ref mac) => {
@@ -647,6 +648,10 @@ pub fn walk_mac<'a, V: Visitor<'a>>(_: &mut V, _: &Mac) {
     // Empty!
 }
 
+pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) {
+    visitor.visit_expr(&constant.value);
+}
+
 pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
     for attr in expression.attrs.iter() {
         visitor.visit_attribute(attr);
@@ -660,7 +665,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         }
         ExprKind::Repeat(ref element, ref count) => {
             visitor.visit_expr(element);
-            visitor.visit_expr(count)
+            visitor.visit_anon_const(count)
         }
         ExprKind::Struct(ref path, ref fields, ref optional_base) => {
             visitor.visit_path(path, expression.id);
diff --git a/src/test/compile-fail/issue-48838.rs b/src/test/compile-fail/issue-48838.rs
new file mode 100644
index 00000000000..ab52a32869f
--- /dev/null
+++ b/src/test/compile-fail/issue-48838.rs
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Functions {
+    Square = |x| x, //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-50600.rs b/src/test/compile-fail/issue-50600.rs
new file mode 100644
index 00000000000..6169a7770bf
--- /dev/null
+++ b/src/test/compile-fail/issue-50600.rs
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo (
+    fn([u8; |x: u8| {}]), //~ ERROR mismatched types
+);
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-50688.rs b/src/test/compile-fail/issue-50688.rs
new file mode 100644
index 00000000000..ff45cf639de
--- /dev/null
+++ b/src/test/compile-fail/issue-50688.rs
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    [1; || {}]; //~ ERROR mismatched types
+}
diff --git a/src/test/run-pass/issue-50689.rs b/src/test/run-pass/issue-50689.rs
new file mode 100644
index 00000000000..d437b9d88f4
--- /dev/null
+++ b/src/test/run-pass/issue-50689.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo {
+    Bar = (|x: i32| { }, 42).1,
+}
+
+fn main() {
+    assert_eq!(Foo::Bar as usize, 42);
+}
diff --git a/src/test/ui/issue-23302-1.stderr b/src/test/ui/issue-23302-1.stderr
index 6ff46a7e21f..dcf021de57e 100644
--- a/src/test/ui/issue-23302-1.stderr
+++ b/src/test/ui/issue-23302-1.stderr
@@ -1,11 +1,11 @@
-error[E0391]: cycle detected when processing `X::A::{{initializer}}`
+error[E0391]: cycle detected when processing `X::A::{{constant}}`
   --> $DIR/issue-23302-1.rs:14:9
    |
 LL |     A = X::A as isize, //~ ERROR E0391
    |         ^^^^^^^^^^^^^
    |
-   = note: ...which again requires processing `X::A::{{initializer}}`, completing the cycle
-note: cycle used when const-evaluating `X::A::{{initializer}}`
+   = note: ...which again requires processing `X::A::{{constant}}`, completing the cycle
+note: cycle used when const-evaluating `X::A::{{constant}}`
   --> $DIR/issue-23302-1.rs:14:9
    |
 LL |     A = X::A as isize, //~ ERROR E0391
diff --git a/src/test/ui/issue-23302-2.stderr b/src/test/ui/issue-23302-2.stderr
index 6b72a5b544d..146f86127c5 100644
--- a/src/test/ui/issue-23302-2.stderr
+++ b/src/test/ui/issue-23302-2.stderr
@@ -1,11 +1,11 @@
-error[E0391]: cycle detected when processing `Y::A::{{initializer}}`
+error[E0391]: cycle detected when processing `Y::A::{{constant}}`
   --> $DIR/issue-23302-2.rs:14:9
    |
 LL |     A = Y::B as isize, //~ ERROR E0391
    |         ^^^^^^^^^^^^^
    |
-   = note: ...which again requires processing `Y::A::{{initializer}}`, completing the cycle
-note: cycle used when const-evaluating `Y::A::{{initializer}}`
+   = note: ...which again requires processing `Y::A::{{constant}}`, completing the cycle
+note: cycle used when const-evaluating `Y::A::{{constant}}`
   --> $DIR/issue-23302-2.rs:14:9
    |
 LL |     A = Y::B as isize, //~ ERROR E0391
diff --git a/src/test/ui/issue-36163.stderr b/src/test/ui/issue-36163.stderr
index 7199fffd386..5623437669f 100644
--- a/src/test/ui/issue-36163.stderr
+++ b/src/test/ui/issue-36163.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when processing `Foo::B::{{initializer}}`
+error[E0391]: cycle detected when processing `Foo::B::{{constant}}`
   --> $DIR/issue-36163.rs:14:9
    |
 LL |     B = A, //~ ERROR E0391
@@ -9,8 +9,8 @@ note: ...which requires processing `A`...
    |
 LL | const A: isize = Foo::B as isize;
    |                  ^^^^^^^^^^^^^^^
-   = note: ...which again requires processing `Foo::B::{{initializer}}`, completing the cycle
-note: cycle used when const-evaluating `Foo::B::{{initializer}}`
+   = note: ...which again requires processing `Foo::B::{{constant}}`, completing the cycle
+note: cycle used when const-evaluating `Foo::B::{{constant}}`
   --> $DIR/issue-36163.rs:14:9
    |
 LL |     B = A, //~ ERROR E0391