1
Fork 0

rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants".

This commit is contained in:
Eduard-Mihai Burtescu 2018-05-17 21:28:50 +03:00
parent 072b0f617f
commit 26aad25487
35 changed files with 334 additions and 306 deletions

View file

@ -272,6 +272,9 @@ pub trait Visitor<'v> : Sized {
fn visit_decl(&mut self, d: &'v Decl) { fn visit_decl(&mut self, d: &'v Decl) {
walk_decl(self, d) 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) { fn visit_expr(&mut self, ex: &'v Expr) {
walk_expr(self, ex) walk_expr(self, ex)
} }
@ -547,7 +550,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
generics, generics,
parent_item_id, parent_item_id,
variant.span); 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); 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) => { TyPath(ref qpath) => {
visitor.visit_qpath(qpath, typ.id, typ.span); visitor.visit_qpath(qpath, typ.id, typ.span);
} }
TyArray(ref ty, length) => { TyArray(ref ty, ref length) => {
visitor.visit_ty(ty); visitor.visit_ty(ty);
visitor.visit_nested_body(length) visitor.visit_anon_const(length)
} }
TyTraitObject(ref bounds, ref lifetime) => { TyTraitObject(ref bounds, ref lifetime) => {
for bound in bounds { 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_ty_param_bound, bounds);
walk_list!(visitor, visit_lifetime, lifetimes); walk_list!(visitor, visit_lifetime, lifetimes);
} }
TyTypeof(expression) => { TyTypeof(ref expression) => {
visitor.visit_nested_body(expression) visitor.visit_anon_const(expression)
} }
TyInfer | TyErr => {} 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) { pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_id(expression.id); visitor.visit_id(expression.id);
walk_list!(visitor, visit_attribute, expression.attrs.iter()); 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) => { ExprArray(ref subexpressions) => {
walk_list!(visitor, visit_expr, subexpressions); walk_list!(visitor, visit_expr, subexpressions);
} }
ExprRepeat(ref element, count) => { ExprRepeat(ref element, ref count) => {
visitor.visit_expr(element); visitor.visit_expr(element);
visitor.visit_nested_body(count) visitor.visit_anon_const(count)
} }
ExprStruct(ref qpath, ref fields, ref optional_base) => { ExprStruct(ref qpath, ref fields, ref optional_base) => {
visitor.visit_qpath(qpath, expression.id, expression.span); visitor.visit_qpath(qpath, expression.id, expression.span);

View file

@ -1080,12 +1080,10 @@ impl<'a> LoweringContext<'a> {
}), }),
)), )),
TyKind::Array(ref ty, ref length) => { TyKind::Array(ref ty, ref length) => {
let length = self.lower_body(None, |this| this.lower_expr(length)); hir::TyArray(self.lower_ty(ty, itctx), self.lower_anon_const(length))
hir::TyArray(self.lower_ty(ty, itctx), length)
} }
TyKind::Typeof(ref expr) => { TyKind::Typeof(ref expr) => {
let expr = self.lower_body(None, |this| this.lower_expr(expr)); hir::TyTypeof(self.lower_anon_const(expr))
hir::TyTypeof(expr)
} }
TyKind::TraitObject(ref bounds, kind) => { TyKind::TraitObject(ref bounds, kind) => {
let mut lifetime_bound = None; let mut lifetime_bound = None;
@ -1365,10 +1363,7 @@ impl<'a> LoweringContext<'a> {
name: v.node.ident.name, name: v.node.ident.name,
attrs: self.lower_attrs(&v.node.attrs), attrs: self.lower_attrs(&v.node.attrs),
data: self.lower_variant_data(&v.node.data), data: self.lower_variant_data(&v.node.data),
disr_expr: v.node disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
.disr_expr
.as_ref()
.map(|e| self.lower_body(None, |this| this.lower_expr(e))),
}, },
span: v.span, 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 { fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let kind = match e.node { let kind = match e.node {
ExprKind::Box(ref inner) => hir::ExprBox(P(self.lower_expr(inner))), 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) => { ExprKind::Repeat(ref expr, ref count) => {
let expr = P(self.lower_expr(expr)); 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) hir::ExprRepeat(expr, count)
} }
ExprKind::Tup(ref elts) => { ExprKind::Tup(ref elts) => {

View file

@ -202,6 +202,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n), NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
NodeVariant(n) => EntryVariant(parent, dep_node_index, n), NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
NodeField(n) => EntryField(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), NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
NodeStmt(n) => EntryStmt(parent, dep_node_index, n), NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
NodeTy(n) => EntryTy(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) { fn visit_expr(&mut self, expr: &'hir Expr) {
self.insert(expr.id, NodeExpr(expr)); self.insert(expr.id, NodeExpr(expr));

View file

@ -33,7 +33,6 @@ pub struct DefCollector<'a> {
pub struct MacroInvocationData { pub struct MacroInvocationData {
pub mark: Mark, pub mark: Mark,
pub def_index: DefIndex, pub def_index: DefIndex,
pub const_expr: bool,
} }
impl<'a> DefCollector<'a> { impl<'a> DefCollector<'a> {
@ -74,25 +73,10 @@ impl<'a> DefCollector<'a> {
self.parent_def = parent; self.parent_def = parent;
} }
pub fn visit_const_expr(&mut self, expr: &Expr) { fn visit_macro_invoc(&mut self, id: NodeId) {
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) {
if let Some(ref mut visit) = self.visit_macro_invoc { if let Some(ref mut visit) = self.visit_macro_invoc {
visit(MacroInvocationData { visit(MacroInvocationData {
mark: id.placeholder_to_mark(), mark: id.placeholder_to_mark(),
const_expr,
def_index: self.parent_def.unwrap(), def_index: self.parent_def.unwrap(),
}) })
} }
@ -119,7 +103,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
DefPathData::ValueNs(i.ident.name.as_interned_str()), DefPathData::ValueNs(i.ident.name.as_interned_str()),
ItemKind::MacroDef(..) => DefPathData::MacroDef(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::GlobalAsm(..) => DefPathData::Misc,
ItemKind::Use(..) => { ItemKind::Use(..) => {
return visit::walk_item(self, i); return visit::walk_item(self, i);
@ -129,30 +113,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
self.with_parent(def, |this| { self.with_parent(def, |this| {
match i.node { 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, _) => { ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor. // If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() { if !struct_def.is_struct() {
@ -161,15 +121,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
REGULAR_SPACE, REGULAR_SPACE,
i.span); 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) { fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
if let ForeignItemKind::Macro(_) = foreign_item.node { 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, 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) { fn visit_generic_param(&mut self, param: &'a GenericParam) {
match *param { match *param {
GenericParam::Lifetime(ref lifetime_def) => { GenericParam::Lifetime(ref lifetime_def) => {
@ -227,7 +200,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
TraitItemKind::Type(..) => { TraitItemKind::Type(..) => {
DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str()) 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); 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(..) => ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
DefPathData::ValueNs(ii.ident.name.as_interned_str()), DefPathData::ValueNs(ii.ident.name.as_interned_str()),
ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(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); 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) { fn visit_pat(&mut self, pat: &'a Pat) {
match pat.node { 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), _ => 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) { fn visit_expr(&mut self, expr: &'a Expr) {
let parent_def = self.parent_def; let parent_def = self.parent_def;
match expr.node { match expr.node {
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false), ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
ExprKind::Closure(..) => { ExprKind::Closure(..) => {
let def = self.create_def(expr.id, let def = self.create_def(expr.id,
DefPathData::ClosureExpr, DefPathData::ClosureExpr,
@ -275,12 +255,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_ty(&mut self, ty: &'a Ty) { fn visit_ty(&mut self, ty: &'a Ty) {
match ty.node { match ty.node {
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false), TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
TyKind::Array(_, ref length) => self.visit_const_expr(length),
TyKind::ImplTrait(..) => { TyKind::ImplTrait(..) => {
self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span); 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); 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) { fn visit_stmt(&mut self, stmt: &'a Stmt) {
match stmt.node { 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), _ => visit::walk_stmt(self, stmt),
} }
} }
@ -298,7 +276,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
match nt.0 { match nt.0 {
token::NtExpr(ref expr) => { token::NtExpr(ref expr) => {
if let ExprKind::Mac(..) = expr.node { if let ExprKind::Mac(..) = expr.node {
self.visit_macro_invoc(expr.id, false); self.visit_macro_invoc(expr.id);
} }
} }
_ => {} _ => {}

View file

@ -231,9 +231,8 @@ impl DefKey {
DefPathData::Misc | DefPathData::Misc |
DefPathData::ClosureExpr | DefPathData::ClosureExpr |
DefPathData::StructCtor | DefPathData::StructCtor |
DefPathData::Initializer | DefPathData::AnonConst |
DefPathData::ImplTrait | DefPathData::ImplTrait => {}
DefPathData::Typeof => {}
}; };
disambiguator.hash(&mut hasher); disambiguator.hash(&mut hasher);
@ -389,12 +388,10 @@ pub enum DefPathData {
Field(InternedString), Field(InternedString),
/// Implicit ctor for a tuple-like struct /// Implicit ctor for a tuple-like struct
StructCtor, StructCtor,
/// Initializer for a const /// A constant expression (see {ast,hir}::AnonConst).
Initializer, AnonConst,
/// An `impl Trait` type node. /// An `impl Trait` type node.
ImplTrait, ImplTrait,
/// A `typeof` type node.
Typeof,
/// GlobalMetaData identifies a piece of crate metadata that is global to /// GlobalMetaData identifies a piece of crate metadata that is global to
/// a whole crate (as opposed to just one item). GlobalMetaData components /// a whole crate (as opposed to just one item). GlobalMetaData components
@ -665,9 +662,8 @@ impl DefPathData {
Misc | Misc |
ClosureExpr | ClosureExpr |
StructCtor | StructCtor |
Initializer | AnonConst |
ImplTrait | ImplTrait => None
Typeof => None
} }
} }
@ -696,9 +692,8 @@ impl DefPathData {
Misc => "{{?}}", Misc => "{{?}}",
ClosureExpr => "{{closure}}", ClosureExpr => "{{closure}}",
StructCtor => "{{constructor}}", StructCtor => "{{constructor}}",
Initializer => "{{initializer}}", AnonConst => "{{constant}}",
ImplTrait => "{{impl-Trait}}", ImplTrait => "{{impl-Trait}}",
Typeof => "{{typeof}}",
}; };
Symbol::intern(s).as_interned_str() Symbol::intern(s).as_interned_str()

View file

@ -53,6 +53,7 @@ pub enum Node<'hir> {
NodeImplItem(&'hir ImplItem), NodeImplItem(&'hir ImplItem),
NodeVariant(&'hir Variant), NodeVariant(&'hir Variant),
NodeField(&'hir StructField), NodeField(&'hir StructField),
NodeAnonConst(&'hir AnonConst),
NodeExpr(&'hir Expr), NodeExpr(&'hir Expr),
NodeStmt(&'hir Stmt), NodeStmt(&'hir Stmt),
NodeTy(&'hir Ty), NodeTy(&'hir Ty),
@ -85,6 +86,7 @@ enum MapEntry<'hir> {
EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem), EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem),
EntryVariant(NodeId, DepNodeIndex, &'hir Variant), EntryVariant(NodeId, DepNodeIndex, &'hir Variant),
EntryField(NodeId, DepNodeIndex, &'hir StructField), EntryField(NodeId, DepNodeIndex, &'hir StructField),
EntryAnonConst(NodeId, DepNodeIndex, &'hir AnonConst),
EntryExpr(NodeId, DepNodeIndex, &'hir Expr), EntryExpr(NodeId, DepNodeIndex, &'hir Expr),
EntryStmt(NodeId, DepNodeIndex, &'hir Stmt), EntryStmt(NodeId, DepNodeIndex, &'hir Stmt),
EntryTy(NodeId, DepNodeIndex, &'hir Ty), EntryTy(NodeId, DepNodeIndex, &'hir Ty),
@ -120,6 +122,7 @@ impl<'hir> MapEntry<'hir> {
EntryImplItem(id, _, _) => id, EntryImplItem(id, _, _) => id,
EntryVariant(id, _, _) => id, EntryVariant(id, _, _) => id,
EntryField(id, _, _) => id, EntryField(id, _, _) => id,
EntryAnonConst(id, _, _) => id,
EntryExpr(id, _, _) => id, EntryExpr(id, _, _) => id,
EntryStmt(id, _, _) => id, EntryStmt(id, _, _) => id,
EntryTy(id, _, _) => id, EntryTy(id, _, _) => id,
@ -147,6 +150,7 @@ impl<'hir> MapEntry<'hir> {
EntryImplItem(_, _, n) => NodeImplItem(n), EntryImplItem(_, _, n) => NodeImplItem(n),
EntryVariant(_, _, n) => NodeVariant(n), EntryVariant(_, _, n) => NodeVariant(n),
EntryField(_, _, n) => NodeField(n), EntryField(_, _, n) => NodeField(n),
EntryAnonConst(_, _, n) => NodeAnonConst(n),
EntryExpr(_, _, n) => NodeExpr(n), EntryExpr(_, _, n) => NodeExpr(n),
EntryStmt(_, _, n) => NodeStmt(n), EntryStmt(_, _, n) => NodeStmt(n),
EntryTy(_, _, n) => NodeTy(n), EntryTy(_, _, n) => NodeTy(n),
@ -193,6 +197,8 @@ impl<'hir> MapEntry<'hir> {
} }
} }
EntryAnonConst(_, _, constant) => Some(constant.body),
EntryExpr(_, _, expr) => { EntryExpr(_, _, expr) => {
match expr.node { match expr.node {
ExprClosure(.., body, _, _) => Some(body), ExprClosure(.., body, _, _) => Some(body),
@ -290,6 +296,7 @@ impl<'hir> Map<'hir> {
EntryLifetime(_, dep_node_index, _) | EntryLifetime(_, dep_node_index, _) |
EntryTyParam(_, dep_node_index, _) | EntryTyParam(_, dep_node_index, _) |
EntryVisibility(_, dep_node_index, _) | EntryVisibility(_, dep_node_index, _) |
EntryAnonConst(_, dep_node_index, _) |
EntryExpr(_, dep_node_index, _) | EntryExpr(_, dep_node_index, _) |
EntryLocal(_, dep_node_index, _) | EntryLocal(_, dep_node_index, _) |
EntryMacroDef(dep_node_index, _) | EntryMacroDef(dep_node_index, _) |
@ -434,6 +441,7 @@ impl<'hir> Map<'hir> {
Some(Def::Variant(def_id)) Some(Def::Variant(def_id))
} }
NodeField(_) | NodeField(_) |
NodeAnonConst(_) |
NodeExpr(_) | NodeExpr(_) |
NodeStmt(_) | NodeStmt(_) |
NodeTy(_) | NodeTy(_) |
@ -495,15 +503,11 @@ impl<'hir> Map<'hir> {
/// Returns the `NodeId` that corresponds to the definition of /// Returns the `NodeId` that corresponds to the definition of
/// which this is the body of, i.e. a `fn`, `const` or `static` /// which this is the body of, i.e. a `fn`, `const` or `static`
/// item (possibly associated), or a closure, or the body itself /// item (possibly associated), a closure, or a `hir::AnonConst`.
/// for embedded constant expressions (e.g. `N` in `[T; N]`).
pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId {
let parent = self.get_parent_node(node_id); let parent = self.get_parent_node(node_id);
if self.map[parent.as_usize()].is_body_owner(node_id) { assert!(self.map[parent.as_usize()].is_body_owner(node_id));
parent parent
} else {
node_id
}
} }
pub fn body_owner_def_id(&self, id: BodyId) -> DefId { 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)); self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody));
} }
if let Some(body_id) = entry.associated_body() { 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
}
}
} else { } else {
bug!("no entry for id `{}`", id) bug!("no entry for id `{}`", id)
} }
@ -547,17 +539,11 @@ impl<'hir> Map<'hir> {
} }
pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind { 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) { match self.get(id) {
NodeItem(&Item { node: ItemConst(..), .. }) | NodeItem(&Item { node: ItemConst(..), .. }) |
NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) | NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => { NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) |
NodeAnonConst(_) => {
BodyOwnerKind::Const BodyOwnerKind::Const
} }
NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => { NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => {
@ -982,6 +968,7 @@ impl<'hir> Map<'hir> {
Some(EntryImplItem(_, _, impl_item)) => impl_item.span, Some(EntryImplItem(_, _, impl_item)) => impl_item.span,
Some(EntryVariant(_, _, variant)) => variant.span, Some(EntryVariant(_, _, variant)) => variant.span,
Some(EntryField(_, _, field)) => field.span, Some(EntryField(_, _, field)) => field.span,
Some(EntryAnonConst(_, _, constant)) => self.body(constant.body).value.span,
Some(EntryExpr(_, _, expr)) => expr.span, Some(EntryExpr(_, _, expr)) => expr.span,
Some(EntryStmt(_, _, stmt)) => stmt.span, Some(EntryStmt(_, _, stmt)) => stmt.span,
Some(EntryTy(_, _, ty)) => ty.span, Some(EntryTy(_, _, ty)) => ty.span,
@ -1201,6 +1188,7 @@ impl<'a> print::State<'a> {
NodeTraitItem(a) => self.print_trait_item(a), NodeTraitItem(a) => self.print_trait_item(a),
NodeImplItem(a) => self.print_impl_item(a), NodeImplItem(a) => self.print_impl_item(a),
NodeVariant(a) => self.print_variant(&a), NodeVariant(a) => self.print_variant(&a),
NodeAnonConst(a) => self.print_anon_const(&a),
NodeExpr(a) => self.print_expr(&a), NodeExpr(a) => self.print_expr(&a),
NodeStmt(a) => self.print_stmt(&a), NodeStmt(a) => self.print_stmt(&a),
NodeTy(a) => self.print_type(&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, field.name,
path_str(), id_str) path_str(), id_str)
} }
Some(NodeAnonConst(_)) => {
format!("const {}{}", map.node_to_pretty_string(id), id_str)
}
Some(NodeExpr(_)) => { Some(NodeExpr(_)) => {
format!("expr {}{}", map.node_to_pretty_string(id), id_str) format!("expr {}{}", map.node_to_pretty_string(id), id_str)
} }

View file

@ -1272,6 +1272,18 @@ pub enum BodyOwnerKind {
Static(Mutability), 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 /// An expression
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
pub struct Expr { pub struct Expr {
@ -1419,7 +1431,7 @@ pub enum Expr_ {
/// ///
/// For example, `[1; 5]`. The first expression is the element /// For example, `[1; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it. /// 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. /// A suspension point for generators. This is `yield <expr>` in Rust.
ExprYield(P<Expr>), ExprYield(P<Expr>),
@ -1677,7 +1689,7 @@ pub enum Ty_ {
/// A variable length slice (`[T]`) /// A variable length slice (`[T]`)
TySlice(P<Ty>), TySlice(P<Ty>),
/// A fixed length array (`[T; n]`) /// A fixed length array (`[T; n]`)
TyArray(P<Ty>, BodyId), TyArray(P<Ty>, AnonConst),
/// A raw pointer (`*const T` or `*mut T`) /// A raw pointer (`*const T` or `*mut T`)
TyPtr(MutTy), TyPtr(MutTy),
/// A reference (`&'a T` or `&'a mut T`) /// A reference (`&'a T` or `&'a mut T`)
@ -1709,7 +1721,7 @@ pub enum Ty_ {
/// so they are resolved directly through the parent `Generics`. /// so they are resolved directly through the parent `Generics`.
TyImplTraitExistential(ExistTy, HirVec<Lifetime>), TyImplTraitExistential(ExistTy, HirVec<Lifetime>),
/// Unused for now /// Unused for now
TyTypeof(BodyId), TyTypeof(AnonConst),
/// TyInfer means the type should be inferred instead of it having been /// TyInfer means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type. /// specified. This can appear anywhere in a type.
TyInfer, TyInfer,
@ -1882,7 +1894,7 @@ pub struct Variant_ {
pub attrs: HirVec<Attribute>, pub attrs: HirVec<Attribute>,
pub data: VariantData, pub data: VariantData,
/// Explicit discriminant, eg `Foo = 1` /// Explicit discriminant, eg `Foo = 1`
pub disr_expr: Option<BodyId>, pub disr_expr: Option<AnonConst>,
} }
pub type Variant = Spanned<Variant_>; pub type Variant = Spanned<Variant_>;

View file

@ -416,16 +416,16 @@ impl<'a> State<'a> {
hir::TyImplTraitExistential(ref existty, ref _lifetimes) => { hir::TyImplTraitExistential(ref existty, ref _lifetimes) => {
self.print_bounds("impl", &existty.bounds[..])?; self.print_bounds("impl", &existty.bounds[..])?;
} }
hir::TyArray(ref ty, v) => { hir::TyArray(ref ty, ref length) => {
self.s.word("[")?; self.s.word("[")?;
self.print_type(&ty)?; self.print_type(&ty)?;
self.s.word("; ")?; self.s.word("; ")?;
self.ann.nested(self, Nested::Body(v))?; self.print_anon_const(length)?;
self.s.word("]")?; self.s.word("]")?;
} }
hir::TyTypeof(e) => { hir::TyTypeof(ref e) => {
self.s.word("typeof(")?; self.s.word("typeof(")?;
self.ann.nested(self, Nested::Body(e))?; self.print_anon_const(e)?;
self.s.word(")")?; self.s.word(")")?;
} }
hir::TyInfer => { hir::TyInfer => {
@ -871,10 +871,10 @@ impl<'a> State<'a> {
self.head("")?; self.head("")?;
let generics = hir::Generics::empty(); let generics = hir::Generics::empty();
self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?; 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.s.space()?;
self.word_space("=")?; self.word_space("=")?;
self.ann.nested(self, Nested::Body(d))?; self.print_anon_const(d)?;
} }
Ok(()) Ok(())
} }
@ -1091,6 +1091,9 @@ impl<'a> State<'a> {
self.print_else(elseopt) 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<()> { fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
self.popen()?; self.popen()?;
@ -1141,12 +1144,12 @@ impl<'a> State<'a> {
self.end() 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.ibox(indent_unit)?;
self.s.word("[")?; self.s.word("[")?;
self.print_expr(element)?; self.print_expr(element)?;
self.word_space(";")?; self.word_space(";")?;
self.ann.nested(self, Nested::Body(count))?; self.print_anon_const(count)?;
self.s.word("]")?; self.s.word("]")?;
self.end() self.end()
} }
@ -1288,7 +1291,7 @@ impl<'a> State<'a> {
hir::ExprArray(ref exprs) => { hir::ExprArray(ref exprs) => {
self.print_expr_vec(exprs)?; self.print_expr_vec(exprs)?;
} }
hir::ExprRepeat(ref element, count) => { hir::ExprRepeat(ref element, ref count) => {
self.print_expr_repeat(&element, count)?; self.print_expr_repeat(&element, count)?;
} }
hir::ExprStruct(ref qpath, ref fields, ref wth) => { hir::ExprStruct(ref qpath, ref fields, ref wth) => {

View file

@ -553,6 +553,12 @@ impl_stable_hash_for!(enum hir::UnsafeSource {
UserProvided UserProvided
}); });
impl_stable_hash_for!(struct hir::AnonConst {
id,
hir_id,
body
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr { impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr {
fn hash_stable<W: StableHasherResult>(&self, fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>, hcx: &mut StableHashingContext<'a>,

View file

@ -214,11 +214,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
data @ DefPathData::LifetimeDef(..) | data @ DefPathData::LifetimeDef(..) |
data @ DefPathData::EnumVariant(..) | data @ DefPathData::EnumVariant(..) |
data @ DefPathData::Field(..) | data @ DefPathData::Field(..) |
data @ DefPathData::Initializer | data @ DefPathData::AnonConst |
data @ DefPathData::MacroDef(..) | data @ DefPathData::MacroDef(..) |
data @ DefPathData::ClosureExpr | data @ DefPathData::ClosureExpr |
data @ DefPathData::ImplTrait | data @ DefPathData::ImplTrait |
data @ DefPathData::Typeof |
data @ DefPathData::GlobalMetaData(..) => { data @ DefPathData::GlobalMetaData(..) => {
let parent_def_id = self.parent_def_id(def_id).unwrap(); let parent_def_id = self.parent_def_id(def_id).unwrap();
self.push_item_path(buffer, parent_def_id); self.push_item_path(buffer, parent_def_id);

View file

@ -290,9 +290,8 @@ impl PrintContext {
DefPathData::LifetimeDef(_) | DefPathData::LifetimeDef(_) |
DefPathData::Field(_) | DefPathData::Field(_) |
DefPathData::StructCtor | DefPathData::StructCtor |
DefPathData::Initializer | DefPathData::AnonConst |
DefPathData::ImplTrait | DefPathData::ImplTrait |
DefPathData::Typeof |
DefPathData::GlobalMetaData(_) => { DefPathData::GlobalMetaData(_) => {
// if we're making a symbol for something, there ought // if we're making a symbol for something, there ought
// to be a value or type-def or something in there // to be a value or type-def or something in there

View file

@ -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> { fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_embedded_const({:?})", def_id); debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id);
let tcx = self.tcx; let tcx = self.tcx;
let id = tcx.hir.as_local_node_id(def_id).unwrap(); let id = tcx.hir.as_local_node_id(def_id).unwrap();
let body_id = tcx.hir.body_owned_by(id); 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) { id: ast::NodeId) {
intravisit::walk_variant(self, v, g, id); intravisit::walk_variant(self, v, g, id);
if let Some(discr) = v.node.disr_expr { if let Some(ref discr) = v.node.disr_expr {
let def_id = self.index.tcx.hir.body_owner_def_id(discr); let def_id = self.index.tcx.hir.local_def_id(discr.id);
self.index.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id); self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
} }
} }
fn visit_generics(&mut self, generics: &'tcx hir::Generics) { 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); let def_id = self.tcx.hir.local_def_id(ty.id);
self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id); self.record(def_id, IsolatedEncoder::encode_info_for_anon_ty, def_id);
} }
hir::TyArray(_, len) => { hir::TyArray(_, ref length) => {
let def_id = self.tcx.hir.body_owner_def_id(len); let def_id = self.tcx.hir.local_def_id(length.id);
self.record(def_id, IsolatedEncoder::encode_info_for_embedded_const, def_id); self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
} }
_ => {} _ => {}
} }

View file

@ -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. // Figure out what primary body this item has.
let body_id = match tcx.hir.get(id) { 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) => hir::map::NodeVariant(variant) =>
return create_constructor_shim(tcx, id, &variant.node.data), return create_constructor_shim(tcx, id, &variant.node.data),
hir::map::NodeStructCtor(ctor) => hir::map::NodeStructCtor(ctor) =>
return create_constructor_shim(tcx, id, 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| { tcx.infer_ctxt().enter(|infcx| {

View file

@ -506,9 +506,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
} }
// Now comes the rote stuff: // Now comes the rote stuff:
hir::ExprRepeat(ref v, count) => { hir::ExprRepeat(ref v, ref count) => {
let c = &cx.tcx.hir.body(count).value; let def_id = cx.tcx.hir.local_def_id(count.id);
let def_id = cx.tcx.hir.body_owner_def_id(count);
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id); let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
let instance = ty::Instance::resolve( let instance = ty::Instance::resolve(
cx.tcx.global_tcx(), cx.tcx.global_tcx(),
@ -520,7 +519,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
instance, instance,
promoted: None 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), Ok(cv) => cv.unwrap_usize(cx.tcx),
Err(e) => { Err(e) => {
e.report(cx.tcx, cx.tcx.def_span(def_id), "array length"); e.report(cx.tcx, cx.tcx.def_span(def_id), "array length");

View file

@ -802,6 +802,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
fn visit_block(&mut self, block: &'tcx Block) { fn visit_block(&mut self, block: &'tcx Block) {
self.resolve_block(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) { fn visit_expr(&mut self, expr: &'tcx Expr) {
self.resolve_expr(expr, None); self.resolve_expr(expr, None);
} }
@ -819,13 +824,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
.map_or(Def::Err, |d| d.def()); .map_or(Def::Err, |d| d.def());
self.record_def(ty.id, PathResolution::new(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); 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)); &tref.trait_ref.path, PathSource::Trait(AliasPossibility::Maybe));
visit::walk_poly_trait_ref(self, tref, m); 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) { fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) {
let type_parameters = match foreign_item.node { let type_parameters = match foreign_item.node {
ForeignItemKind::Fn(_, ref generics) => { ForeignItemKind::Fn(_, ref generics) => {
@ -3820,12 +3800,6 @@ impl<'a> Resolver<'a> {
self.visit_path_segment(expr.span, segment); 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) => { ExprKind::Call(ref callee, ref arguments) => {
self.resolve_expr(callee, Some(expr)); self.resolve_expr(callee, Some(expr));
for argument in arguments { for argument in arguments {

View file

@ -45,9 +45,6 @@ use rustc_data_structures::sync::Lrc;
pub struct InvocationData<'a> { pub struct InvocationData<'a> {
pub module: Cell<Module<'a>>, pub module: Cell<Module<'a>>,
pub def_index: DefIndex, 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. // The scope in which the invocation path is resolved.
pub legacy_scope: Cell<LegacyScope<'a>>, pub legacy_scope: Cell<LegacyScope<'a>>,
// The smallest scope that includes this invocation's expansion, // The smallest scope that includes this invocation's expansion,
@ -60,7 +57,6 @@ impl<'a> InvocationData<'a> {
InvocationData { InvocationData {
module: Cell::new(graph_root), module: Cell::new(graph_root),
def_index: CRATE_DEF_INDEX, def_index: CRATE_DEF_INDEX,
const_expr: false,
legacy_scope: Cell::new(LegacyScope::Empty), legacy_scope: Cell::new(LegacyScope::Empty),
expansion: 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 { self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
module: Cell::new(module), module: Cell::new(module),
def_index: module.def_id().unwrap().index, def_index: module.def_id().unwrap().index,
const_expr: false,
legacy_scope: Cell::new(LegacyScope::Empty), legacy_scope: Cell::new(LegacyScope::Empty),
expansion: Cell::new(LegacyScope::Empty), expansion: Cell::new(LegacyScope::Empty),
})); }));
@ -716,13 +711,12 @@ impl<'a> Resolver<'a> {
invocation: &'a InvocationData<'a>, invocation: &'a InvocationData<'a>,
expansion: &Expansion) { expansion: &Expansion) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self; 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| { let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
invocations.entry(invoc.mark).or_insert_with(|| { invocations.entry(invoc.mark).or_insert_with(|| {
arenas.alloc_invocation_data(InvocationData { arenas.alloc_invocation_data(InvocationData {
def_index: invoc.def_index, def_index: invoc.def_index,
const_expr: invoc.const_expr,
module: Cell::new(graph_root), module: Cell::new(graph_root),
expansion: Cell::new(LegacyScope::Empty), expansion: Cell::new(LegacyScope::Empty),
legacy_scope: 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); let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc); def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| { 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) expansion.visit_with(def_collector)
}); });
} }

View file

@ -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) => { ast::TyKind::Array(ref element, ref length) => {
self.visit_ty(element); 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), _ => 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) => { ast::ExprKind::Repeat(ref element, ref count) => {
self.visit_expr(element); 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, // In particular, we take this branch for call and path expressions,
// where we'll index the idents involved just by continuing to walk. // where we'll index the idents involved just by continuing to walk.

View file

@ -313,7 +313,7 @@ impl Sig for ast::Ty {
} }
ast::TyKind::Array(ref ty, ref v) => { ast::TyKind::Array(ref ty, ref v) => {
let nested_ty = ty.make(offset + 1, id, scx)?; 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); let text = format!("[{}; {}]", nested_ty.text, expr);
Ok(replace_text(nested_ty, text)) Ok(replace_text(nested_ty, text))
} }

View file

@ -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 self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
} }
hir::TyArray(ref ty, length) => { hir::TyArray(ref ty, ref length) => {
let length_def_id = tcx.hir.body_owner_def_id(length); let length_def_id = tcx.hir.local_def_id(length.id);
let substs = Substs::identity_for_item(tcx, length_def_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 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)); let array_ty = tcx.mk_ty(ty::TyArray(self.ast_ty_to_ty(&ty), length));

View file

@ -787,20 +787,7 @@ fn primary_body_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
None, None,
} }
} }
hir::map::NodeExpr(expr) => { hir::map::NodeAnonConst(constant) => Some((constant.body, None)),
// 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)),
}
}
_ => None, _ => None,
} }
} }
@ -1674,8 +1661,8 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
for v in vs { for v in vs {
if let Some(e) = v.node.disr_expr { if let Some(ref e) = v.node.disr_expr {
tcx.typeck_tables_of(tcx.hir.local_def_id(e.node_id)); 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_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 variant_i = tcx.hir.expect_variant(variant_i_node_id);
let i_span = match variant_i.node.disr_expr { 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) None => tcx.hir.span(variant_i_node_id)
}; };
let span = match v.node.disr_expr { 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 None => v.span
}; };
struct_span_err!(tcx.sess, span, E0081, 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) tcx.mk_array(element_ty, args.len() as u64)
} }
hir::ExprRepeat(ref element, count) => { hir::ExprRepeat(ref element, ref count) => {
let count_def_id = tcx.hir.body_owner_def_id(count); let count_def_id = tcx.hir.local_def_id(count.id);
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id); let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
let instance = ty::Instance::resolve( let instance = ty::Instance::resolve(

View file

@ -481,8 +481,8 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// fill the discriminant values and field types // fill the discriminant values and field types
for variant in variants { for variant in variants {
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
prev_discr = Some(if let Some(e) = variant.node.disr_expr { prev_discr = Some(if let Some(ref e) = variant.node.disr_expr {
let expr_did = tcx.hir.local_def_id(e.node_id); let expr_did = tcx.hir.local_def_id(e.id);
def.eval_explicit_discr(tcx, expr_did) def.eval_explicit_discr(tcx, expr_did)
} else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
Some(discr) Some(discr)
@ -565,9 +565,9 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut distance_from_explicit = 0; let mut distance_from_explicit = 0;
(AdtKind::Enum, def.variants.iter().map(|v| { (AdtKind::Enum, def.variants.iter().map(|v| {
let did = tcx.hir.local_def_id(v.node.data.id()); 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; 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 { } else {
ty::VariantDiscr::Relative(distance_from_explicit) 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) tcx.mk_closure(def_id, substs)
} }
NodeExpr(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) { NodeAnonConst(_) => match tcx.hir.get(tcx.hir.get_parent_node(node_id)) {
NodeTy(&hir::Ty { node: TyArray(_, body), .. }) | NodeTy(&hir::Ty { node: TyArray(_, ref constant), .. }) |
NodeTy(&hir::Ty { node: TyTypeof(body), .. }) | NodeTy(&hir::Ty { node: TyTypeof(ref constant), .. }) |
NodeExpr(&hir::Expr { node: ExprRepeat(_, body), .. }) NodeExpr(&hir::Expr { node: ExprRepeat(_, ref constant), .. })
if body.node_id == node_id => tcx.types.usize, if constant.id == node_id => tcx.types.usize,
NodeVariant(&Spanned { node: Variant_ { disr_expr: Some(e), .. }, .. }) NodeVariant(&Spanned { node: Variant_ { disr_expr: Some(ref e), .. }, .. })
if e.node_id == node_id => { if e.id == node_id => {
tcx.adt_def(tcx.hir.get_parent_did(node_id)) tcx.adt_def(tcx.hir.get_parent_did(node_id))
.repr.discr_type().to_ty(tcx) .repr.discr_type().to_ty(tcx)
} }
x => { x => {
bug!("unexpected expr parent in type_of_def_id(): {:?}", x); bug!("unexpected const parent in type_of_def_id(): {:?}", x);
} }
}, },

View file

@ -2669,19 +2669,19 @@ impl Clean<Type> for hir::Ty {
type_: box m.ty.clean(cx)} type_: box m.ty.clean(cx)}
} }
TySlice(ref ty) => Slice(box ty.clean(cx)), TySlice(ref ty) => Slice(box ty.clean(cx)),
TyArray(ref ty, n) => { TyArray(ref ty, ref length) => {
let def_id = cx.tcx.hir.body_owner_def_id(n); let def_id = cx.tcx.hir.local_def_id(length.id);
let param_env = cx.tcx.param_env(def_id); let param_env = cx.tcx.param_env(def_id);
let substs = Substs::identity_for_item(cx.tcx, def_id); let substs = Substs::identity_for_item(cx.tcx, def_id);
let cid = GlobalId { let cid = GlobalId {
instance: ty::Instance::new(def_id, substs), instance: ty::Instance::new(def_id, substs),
promoted: None 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) ty::Const::unevaluated(cx.tcx, def_id, substs, cx.tcx.types.usize)
}); });
let n = print_const(cx, n); let length = print_const(cx, length);
Array(box ty.clean(cx), n) Array(box ty.clean(cx), length)
}, },
TyTup(ref tys) => Tuple(tys.clean(cx)), TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(hir::QPath::Resolved(None, ref path)) => { TyPath(hir::QPath::Resolved(None, ref path)) => {

View file

@ -920,6 +920,18 @@ pub enum UnsafeSource {
UserProvided, 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 /// An expression
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)]
pub struct Expr { pub struct Expr {
@ -1168,9 +1180,9 @@ pub enum ExprKind {
/// An array literal constructed from one repeated element. /// An array literal constructed from one repeated element.
/// ///
/// For example, `[1; 5]`. The first expression is the element /// For example, `[1; 5]`. The expression is the element to be
/// to be repeated; the second is the number of times to repeat it. /// repeated; the constant is the number of times to repeat it.
Repeat(P<Expr>, P<Expr>), Repeat(P<Expr>, AnonConst),
/// No-op: used solely so we can pretty-print faithfully /// No-op: used solely so we can pretty-print faithfully
Paren(P<Expr>), Paren(P<Expr>),
@ -1565,7 +1577,7 @@ pub enum TyKind {
/// A variable-length slice (`[T]`) /// A variable-length slice (`[T]`)
Slice(P<Ty>), Slice(P<Ty>),
/// A fixed length array (`[T; n]`) /// A fixed length array (`[T; n]`)
Array(P<Ty>, P<Expr>), Array(P<Ty>, AnonConst),
/// A raw pointer (`*const T` or `*mut T`) /// A raw pointer (`*const T` or `*mut T`)
Ptr(MutTy), Ptr(MutTy),
/// A reference (`&'a T` or `&'a mut T`) /// 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 /// No-op; kept solely so that we can pretty-print faithfully
Paren(P<Ty>), Paren(P<Ty>),
/// Unused for now /// Unused for now
Typeof(P<Expr>), Typeof(AnonConst),
/// TyKind::Infer means the type should be inferred instead of it having been /// TyKind::Infer means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type. /// specified. This can appear anywhere in a type.
Infer, Infer,
@ -1856,7 +1868,7 @@ pub struct Variant_ {
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub data: VariantData, pub data: VariantData,
/// Explicit discriminant, e.g. `Foo = 1` /// Explicit discriminant, e.g. `Foo = 1`
pub disr_expr: Option<P<Expr>>, pub disr_expr: Option<AnonConst>,
} }
pub type Variant = Spanned<Variant_>; pub type Variant = Spanned<Variant_>;

View file

@ -207,7 +207,10 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
span, span,
ast::TyKind::Tup(vec![ty_str.clone(), ty_str]) 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),
},
), ),
); );

View file

@ -112,6 +112,10 @@ pub trait Folder : Sized {
noop_fold_pat(p, self) 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> { fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
e.map(|e| noop_fold_expr(e, self)) 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::Path(qself, fld.fold_path(path))
} }
TyKind::Array(ty, e) => { TyKind::Array(ty, length) => {
TyKind::Array(fld.fold_ty(ty), fld.fold_expr(e)) TyKind::Array(fld.fold_ty(ty), fld.fold_anon_const(length))
} }
TyKind::Typeof(expr) => { TyKind::Typeof(expr) => {
TyKind::Typeof(fld.fold_expr(expr)) TyKind::Typeof(fld.fold_anon_const(expr))
} }
TyKind::TraitObject(bounds, syntax) => { TyKind::TraitObject(bounds, syntax) => {
TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), 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), ident: fld.fold_ident(v.node.ident),
attrs: fold_attrs(v.node.attrs, fld), attrs: fold_attrs(v.node.attrs, fld),
data: fld.fold_variant_data(v.node.data), 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), 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 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 { pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr {
Expr { Expr {
node: match node { 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::Array(folder.fold_exprs(exprs))
} }
ExprKind::Repeat(expr, count) => { 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::Tup(exprs) => ExprKind::Tup(folder.fold_exprs(exprs)),
ExprKind::Call(f, args) => { ExprKind::Call(f, args) => {

View file

@ -12,7 +12,7 @@ use rustc_target::spec::abi::{self, Abi};
use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy}; use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy};
use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
use ast::Unsafety; 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::Block;
use ast::{BlockCheckMode, CaptureBy, Movability}; use ast::{BlockCheckMode, CaptureBy, Movability};
use ast::{Constness, Crate}; use ast::{Constness, Crate};
@ -1543,7 +1543,10 @@ impl<'a> Parser<'a> {
// Parse optional `; EXPR` in `[TYPE; EXPR]` // Parse optional `; EXPR` in `[TYPE; EXPR]`
let t = match self.maybe_parse_fixed_length_of_vec()? { let t = match self.maybe_parse_fixed_length_of_vec()? {
None => TyKind::Slice(t), 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))?; self.expect(&token::CloseDelim(token::Bracket))?;
t t
@ -1555,7 +1558,10 @@ impl<'a> Parser<'a> {
// `typeof(EXPR)` // `typeof(EXPR)`
// In order to not be ambiguous, the type must be surrounded by parens. // In order to not be ambiguous, the type must be surrounded by parens.
self.expect(&token::OpenDelim(token::Paren))?; 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))?; self.expect(&token::CloseDelim(token::Paren))?;
TyKind::Typeof(e) TyKind::Typeof(e)
} else if self.eat_keyword(keywords::Underscore) { } else if self.eat_keyword(keywords::Underscore) {
@ -2264,7 +2270,10 @@ impl<'a> Parser<'a> {
if self.check(&token::Semi) { if self.check(&token::Semi) {
// Repeating array syntax: [ 0; 512 ] // Repeating array syntax: [ 0; 512 ]
self.bump(); 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))?; self.expect(&token::CloseDelim(token::Bracket))?;
ex = ExprKind::Repeat(first_expr, count); ex = ExprKind::Repeat(first_expr, count);
} else if self.check(&token::Comma) { } else if self.check(&token::Comma) {
@ -6353,8 +6362,11 @@ impl<'a> Parser<'a> {
struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?, struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?,
ast::DUMMY_NODE_ID); ast::DUMMY_NODE_ID);
} else if self.eat(&token::Eq) { } else if self.eat(&token::Eq) {
disr_expr = Some(self.parse_expr()?); disr_expr = Some(AnonConst {
any_disr = disr_expr.as_ref().map(|expr| expr.span); 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); struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);
} else { } else {
struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); struct_def = VariantData::Unit(ast::DUMMY_NODE_ID);

View file

@ -1076,16 +1076,16 @@ impl<'a> State<'a> {
ast::TyKind::ImplTrait(ref bounds) => { ast::TyKind::ImplTrait(ref bounds) => {
self.print_bounds("impl", &bounds[..])?; self.print_bounds("impl", &bounds[..])?;
} }
ast::TyKind::Array(ref ty, ref v) => { ast::TyKind::Array(ref ty, ref length) => {
self.s.word("[")?; self.s.word("[")?;
self.print_type(ty)?; self.print_type(ty)?;
self.s.word("; ")?; self.s.word("; ")?;
self.print_expr(v)?; self.print_expr(&length.value)?;
self.s.word("]")?; self.s.word("]")?;
} }
ast::TyKind::Typeof(ref e) => { ast::TyKind::Typeof(ref e) => {
self.s.word("typeof(")?; self.s.word("typeof(")?;
self.print_expr(e)?; self.print_expr(&e.value)?;
self.s.word(")")?; self.s.word(")")?;
} }
ast::TyKind::Infer => { ast::TyKind::Infer => {
@ -1552,7 +1552,7 @@ impl<'a> State<'a> {
Some(ref d) => { Some(ref d) => {
self.s.space()?; self.s.space()?;
self.word_space("=")?; self.word_space("=")?;
self.print_expr(d) self.print_expr(&d.value)
} }
_ => Ok(()) _ => Ok(())
} }
@ -1905,14 +1905,14 @@ impl<'a> State<'a> {
fn print_expr_repeat(&mut self, fn print_expr_repeat(&mut self,
element: &ast::Expr, element: &ast::Expr,
count: &ast::Expr, count: &ast::AnonConst,
attrs: &[Attribute]) -> io::Result<()> { attrs: &[Attribute]) -> io::Result<()> {
self.ibox(INDENT_UNIT)?; self.ibox(INDENT_UNIT)?;
self.s.word("[")?; self.s.word("[")?;
self.print_inner_attributes_inline(attrs)?; self.print_inner_attributes_inline(attrs)?;
self.print_expr(element)?; self.print_expr(element)?;
self.word_space(";")?; self.word_space(";")?;
self.print_expr(count)?; self.print_expr(&count.value)?;
self.s.word("]")?; self.s.word("]")?;
self.end() self.end()
} }

View file

@ -69,6 +69,7 @@ pub trait Visitor<'ast>: Sized {
fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) } 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_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) } 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(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
fn visit_expr_post(&mut self, _ex: &'ast Expr) { } fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) } 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_ident(variant.node.ident);
visitor.visit_variant_data(&variant.node.data, variant.node.ident, visitor.visit_variant_data(&variant.node.data, variant.node.ident,
generics, item_id, variant.span); 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); 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); visitor.visit_path(path, typ.id);
} }
TyKind::Array(ref ty, ref expression) => { TyKind::Array(ref ty, ref length) => {
visitor.visit_ty(ty); visitor.visit_ty(ty);
visitor.visit_expr(expression) visitor.visit_anon_const(length)
} }
TyKind::TraitObject(ref bounds, ..) | TyKind::TraitObject(ref bounds, ..) |
TyKind::ImplTrait(ref bounds) => { TyKind::ImplTrait(ref bounds) => {
walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_ty_param_bound, bounds);
} }
TyKind::Typeof(ref expression) => { TyKind::Typeof(ref expression) => {
visitor.visit_expr(expression) visitor.visit_anon_const(expression)
} }
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
TyKind::Mac(ref mac) => { TyKind::Mac(ref mac) => {
@ -647,6 +648,10 @@ pub fn walk_mac<'a, V: Visitor<'a>>(_: &mut V, _: &Mac) {
// Empty! // 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) { pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
for attr in expression.attrs.iter() { for attr in expression.attrs.iter() {
visitor.visit_attribute(attr); 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) => { ExprKind::Repeat(ref element, ref count) => {
visitor.visit_expr(element); visitor.visit_expr(element);
visitor.visit_expr(count) visitor.visit_anon_const(count)
} }
ExprKind::Struct(ref path, ref fields, ref optional_base) => { ExprKind::Struct(ref path, ref fields, ref optional_base) => {
visitor.visit_path(path, expression.id); visitor.visit_path(path, expression.id);

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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
}

View file

@ -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);
}

View file

@ -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 --> $DIR/issue-23302-1.rs:14:9
| |
LL | A = X::A as isize, //~ ERROR E0391 LL | A = X::A as isize, //~ ERROR E0391
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
| |
= note: ...which again requires processing `X::A::{{initializer}}`, completing the cycle = note: ...which again requires processing `X::A::{{constant}}`, completing the cycle
note: cycle used when const-evaluating `X::A::{{initializer}}` note: cycle used when const-evaluating `X::A::{{constant}}`
--> $DIR/issue-23302-1.rs:14:9 --> $DIR/issue-23302-1.rs:14:9
| |
LL | A = X::A as isize, //~ ERROR E0391 LL | A = X::A as isize, //~ ERROR E0391

View file

@ -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 --> $DIR/issue-23302-2.rs:14:9
| |
LL | A = Y::B as isize, //~ ERROR E0391 LL | A = Y::B as isize, //~ ERROR E0391
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
| |
= note: ...which again requires processing `Y::A::{{initializer}}`, completing the cycle = note: ...which again requires processing `Y::A::{{constant}}`, completing the cycle
note: cycle used when const-evaluating `Y::A::{{initializer}}` note: cycle used when const-evaluating `Y::A::{{constant}}`
--> $DIR/issue-23302-2.rs:14:9 --> $DIR/issue-23302-2.rs:14:9
| |
LL | A = Y::B as isize, //~ ERROR E0391 LL | A = Y::B as isize, //~ ERROR E0391

View file

@ -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 --> $DIR/issue-36163.rs:14:9
| |
LL | B = A, //~ ERROR E0391 LL | B = A, //~ ERROR E0391
@ -9,8 +9,8 @@ note: ...which requires processing `A`...
| |
LL | const A: isize = Foo::B as isize; LL | const A: isize = Foo::B as isize;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
= note: ...which again requires processing `Foo::B::{{initializer}}`, completing the cycle = note: ...which again requires processing `Foo::B::{{constant}}`, completing the cycle
note: cycle used when const-evaluating `Foo::B::{{initializer}}` note: cycle used when const-evaluating `Foo::B::{{constant}}`
--> $DIR/issue-36163.rs:14:9 --> $DIR/issue-36163.rs:14:9
| |
LL | B = A, //~ ERROR E0391 LL | B = A, //~ ERROR E0391