Skip to content

Commit 538fea5

Browse files
committed
Auto merge of #50851 - eddyb:the-only-constant, r=nikomatsakis
rustc: introduce {ast,hir}::AnonConst to consolidate so-called "embedded constants". Previously, constants in array lengths and enum variant discriminants were "merely an expression", and had no separate ID for, e.g. type-checking or const-eval, instead reusing the expression's. That complicated code working with bodies, because such constants were the only special case where the "owner" of the body wasn't the HIR parent, but rather the same node as the body itself. Also, if the body happened to be a closure, we had no way to allocate a `DefId` for both the constant *and* the closure, leading to *several* bugs (mostly ICEs where type errors were expected). This PR rectifies the situation by adding another (`{ast,hir}::AnonConst`) node around every such constant. Also, const generics are expected to rely on the new `AnonConst` nodes, as well (cc @varkor). * fixes #48838 * fixes #50600 * fixes #50688 * fixes #50689 * obsoletes #50623 r? @nikomatsakis
2 parents a1d4a95 + 26aad25 commit 538fea5

File tree

35 files changed

+336
-320
lines changed

35 files changed

+336
-320
lines changed

src/librustc/hir/intravisit.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ pub trait Visitor<'v> : Sized {
272272
fn visit_decl(&mut self, d: &'v Decl) {
273273
walk_decl(self, d)
274274
}
275+
fn visit_anon_const(&mut self, c: &'v AnonConst) {
276+
walk_anon_const(self, c)
277+
}
275278
fn visit_expr(&mut self, ex: &'v Expr) {
276279
walk_expr(self, ex)
277280
}
@@ -547,7 +550,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
547550
generics,
548551
parent_item_id,
549552
variant.span);
550-
walk_list!(visitor, visit_nested_body, variant.node.disr_expr);
553+
walk_list!(visitor, visit_anon_const, &variant.node.disr_expr);
551554
walk_list!(visitor, visit_attribute, &variant.node.attrs);
552555
}
553556

@@ -576,9 +579,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
576579
TyPath(ref qpath) => {
577580
visitor.visit_qpath(qpath, typ.id, typ.span);
578581
}
579-
TyArray(ref ty, length) => {
582+
TyArray(ref ty, ref length) => {
580583
visitor.visit_ty(ty);
581-
visitor.visit_nested_body(length)
584+
visitor.visit_anon_const(length)
582585
}
583586
TyTraitObject(ref bounds, ref lifetime) => {
584587
for bound in bounds {
@@ -592,8 +595,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
592595
walk_list!(visitor, visit_ty_param_bound, bounds);
593596
walk_list!(visitor, visit_lifetime, lifetimes);
594597
}
595-
TyTypeof(expression) => {
596-
visitor.visit_nested_body(expression)
598+
TyTypeof(ref expression) => {
599+
visitor.visit_anon_const(expression)
597600
}
598601
TyInfer | TyErr => {}
599602
}
@@ -944,6 +947,11 @@ pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
944947
}
945948
}
946949

950+
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
951+
visitor.visit_id(constant.id);
952+
visitor.visit_nested_body(constant.body);
953+
}
954+
947955
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
948956
visitor.visit_id(expression.id);
949957
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) {
954962
ExprArray(ref subexpressions) => {
955963
walk_list!(visitor, visit_expr, subexpressions);
956964
}
957-
ExprRepeat(ref element, count) => {
965+
ExprRepeat(ref element, ref count) => {
958966
visitor.visit_expr(element);
959-
visitor.visit_nested_body(count)
967+
visitor.visit_anon_const(count)
960968
}
961969
ExprStruct(ref qpath, ref fields, ref optional_base) => {
962970
visitor.visit_qpath(qpath, expression.id, expression.span);

src/librustc/hir/lowering.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,12 +1080,10 @@ impl<'a> LoweringContext<'a> {
10801080
}),
10811081
)),
10821082
TyKind::Array(ref ty, ref length) => {
1083-
let length = self.lower_body(None, |this| this.lower_expr(length));
1084-
hir::TyArray(self.lower_ty(ty, itctx), length)
1083+
hir::TyArray(self.lower_ty(ty, itctx), self.lower_anon_const(length))
10851084
}
10861085
TyKind::Typeof(ref expr) => {
1087-
let expr = self.lower_body(None, |this| this.lower_expr(expr));
1088-
hir::TyTypeof(expr)
1086+
hir::TyTypeof(self.lower_anon_const(expr))
10891087
}
10901088
TyKind::TraitObject(ref bounds, kind) => {
10911089
let mut lifetime_bound = None;
@@ -1365,10 +1363,7 @@ impl<'a> LoweringContext<'a> {
13651363
name: v.node.ident.name,
13661364
attrs: self.lower_attrs(&v.node.attrs),
13671365
data: self.lower_variant_data(&v.node.data),
1368-
disr_expr: v.node
1369-
.disr_expr
1370-
.as_ref()
1371-
.map(|e| self.lower_body(None, |this| this.lower_expr(e))),
1366+
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
13721367
},
13731368
span: v.span,
13741369
}
@@ -2927,6 +2922,16 @@ impl<'a> LoweringContext<'a> {
29272922
}
29282923
}
29292924

2925+
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
2926+
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id);
2927+
2928+
hir::AnonConst {
2929+
id: node_id,
2930+
hir_id,
2931+
body: self.lower_body(None, |this| this.lower_expr(&c.value)),
2932+
}
2933+
}
2934+
29302935
fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
29312936
let kind = match e.node {
29322937
ExprKind::Box(ref inner) => hir::ExprBox(P(self.lower_expr(inner))),
@@ -2936,7 +2941,7 @@ impl<'a> LoweringContext<'a> {
29362941
}
29372942
ExprKind::Repeat(ref expr, ref count) => {
29382943
let expr = P(self.lower_expr(expr));
2939-
let count = self.lower_body(None, |this| this.lower_expr(count));
2944+
let count = self.lower_anon_const(count);
29402945
hir::ExprRepeat(expr, count)
29412946
}
29422947
ExprKind::Tup(ref elts) => {

src/librustc/hir/map/collector.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
202202
NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
203203
NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
204204
NodeField(n) => EntryField(parent, dep_node_index, n),
205+
NodeAnonConst(n) => EntryAnonConst(parent, dep_node_index, n),
205206
NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
206207
NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
207208
NodeTy(n) => EntryTy(parent, dep_node_index, n),
@@ -390,6 +391,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
390391
});
391392
}
392393

394+
fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
395+
self.insert(constant.id, NodeAnonConst(constant));
396+
397+
self.with_parent(constant.id, |this| {
398+
intravisit::walk_anon_const(this, constant);
399+
});
400+
}
401+
393402
fn visit_expr(&mut self, expr: &'hir Expr) {
394403
self.insert(expr.id, NodeExpr(expr));
395404

src/librustc/hir/map/def_collector.rs

Lines changed: 42 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ pub struct DefCollector<'a> {
3333
pub struct MacroInvocationData {
3434
pub mark: Mark,
3535
pub def_index: DefIndex,
36-
pub const_expr: bool,
3736
}
3837

3938
impl<'a> DefCollector<'a> {
@@ -74,25 +73,10 @@ impl<'a> DefCollector<'a> {
7473
self.parent_def = parent;
7574
}
7675

77-
pub fn visit_const_expr(&mut self, expr: &Expr) {
78-
match expr.node {
79-
// Find the node which will be used after lowering.
80-
ExprKind::Paren(ref inner) => return self.visit_const_expr(inner),
81-
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, true),
82-
// FIXME(eddyb) Closures should have separate
83-
// function definition IDs and expression IDs.
84-
ExprKind::Closure(..) => return,
85-
_ => {}
86-
}
87-
88-
self.create_def(expr.id, DefPathData::Initializer, REGULAR_SPACE, expr.span);
89-
}
90-
91-
fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
76+
fn visit_macro_invoc(&mut self, id: NodeId) {
9277
if let Some(ref mut visit) = self.visit_macro_invoc {
9378
visit(MacroInvocationData {
9479
mark: id.placeholder_to_mark(),
95-
const_expr,
9680
def_index: self.parent_def.unwrap(),
9781
})
9882
}
@@ -119,7 +103,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
119103
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
120104
DefPathData::ValueNs(i.ident.name.as_interned_str()),
121105
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_interned_str()),
122-
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
106+
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id),
123107
ItemKind::GlobalAsm(..) => DefPathData::Misc,
124108
ItemKind::Use(..) => {
125109
return visit::walk_item(self, i);
@@ -129,30 +113,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
129113

130114
self.with_parent(def, |this| {
131115
match i.node {
132-
ItemKind::Enum(ref enum_definition, _) => {
133-
for v in &enum_definition.variants {
134-
let variant_def_index =
135-
this.create_def(v.node.data.id(),
136-
DefPathData::EnumVariant(v.node.ident
137-
.name.as_interned_str()),
138-
REGULAR_SPACE,
139-
v.span);
140-
this.with_parent(variant_def_index, |this| {
141-
for (index, field) in v.node.data.fields().iter().enumerate() {
142-
let name = field.ident.map(|ident| ident.name)
143-
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
144-
this.create_def(field.id,
145-
DefPathData::Field(name.as_interned_str()),
146-
REGULAR_SPACE,
147-
field.span);
148-
}
149-
150-
if let Some(ref expr) = v.node.disr_expr {
151-
this.visit_const_expr(expr);
152-
}
153-
});
154-
}
155-
}
156116
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
157117
// If this is a tuple-like struct, register the constructor.
158118
if !struct_def.is_struct() {
@@ -161,15 +121,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
161121
REGULAR_SPACE,
162122
i.span);
163123
}
164-
165-
for (index, field) in struct_def.fields().iter().enumerate() {
166-
let name = field.ident.map(|ident| ident.name)
167-
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
168-
this.create_def(field.id,
169-
DefPathData::Field(name.as_interned_str()),
170-
REGULAR_SPACE,
171-
field.span);
172-
}
173124
}
174125
_ => {}
175126
}
@@ -184,7 +135,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
184135

185136
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
186137
if let ForeignItemKind::Macro(_) = foreign_item.node {
187-
return self.visit_macro_invoc(foreign_item.id, false);
138+
return self.visit_macro_invoc(foreign_item.id);
188139
}
189140

190141
let def = self.create_def(foreign_item.id,
@@ -197,6 +148,28 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
197148
});
198149
}
199150

151+
fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
152+
let def = self.create_def(v.node.data.id(),
153+
DefPathData::EnumVariant(v.node.ident
154+
.name.as_interned_str()),
155+
REGULAR_SPACE,
156+
v.span);
157+
self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id));
158+
}
159+
160+
fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,
161+
_: &'a Generics, _: NodeId, _: Span) {
162+
for (index, field) in data.fields().iter().enumerate() {
163+
let name = field.ident.map(|ident| ident.name)
164+
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
165+
let def = self.create_def(field.id,
166+
DefPathData::Field(name.as_interned_str()),
167+
REGULAR_SPACE,
168+
field.span);
169+
self.with_parent(def, |this| this.visit_struct_field(field));
170+
}
171+
}
172+
200173
fn visit_generic_param(&mut self, param: &'a GenericParam) {
201174
match *param {
202175
GenericParam::Lifetime(ref lifetime_def) => {
@@ -227,50 +200,45 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
227200
TraitItemKind::Type(..) => {
228201
DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str())
229202
},
230-
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
203+
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id),
231204
};
232205

233206
let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE, ti.span);
234-
self.with_parent(def, |this| {
235-
if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
236-
this.visit_const_expr(expr);
237-
}
238-
239-
visit::walk_trait_item(this, ti);
240-
});
207+
self.with_parent(def, |this| visit::walk_trait_item(this, ti));
241208
}
242209

243210
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
244211
let def_data = match ii.node {
245212
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
246213
DefPathData::ValueNs(ii.ident.name.as_interned_str()),
247214
ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()),
248-
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
215+
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
249216
};
250217

251218
let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE, ii.span);
252-
self.with_parent(def, |this| {
253-
if let ImplItemKind::Const(_, ref expr) = ii.node {
254-
this.visit_const_expr(expr);
255-
}
256-
257-
visit::walk_impl_item(this, ii);
258-
});
219+
self.with_parent(def, |this| visit::walk_impl_item(this, ii));
259220
}
260221

261222
fn visit_pat(&mut self, pat: &'a Pat) {
262223
match pat.node {
263-
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
224+
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id),
264225
_ => visit::walk_pat(self, pat),
265226
}
266227
}
267228

229+
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
230+
let def = self.create_def(constant.id,
231+
DefPathData::AnonConst,
232+
REGULAR_SPACE,
233+
constant.value.span);
234+
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
235+
}
236+
268237
fn visit_expr(&mut self, expr: &'a Expr) {
269238
let parent_def = self.parent_def;
270239

271240
match expr.node {
272-
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
273-
ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
241+
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
274242
ExprKind::Closure(..) => {
275243
let def = self.create_def(expr.id,
276244
DefPathData::ClosureExpr,
@@ -287,20 +255,18 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
287255

288256
fn visit_ty(&mut self, ty: &'a Ty) {
289257
match ty.node {
290-
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false),
291-
TyKind::Array(_, ref length) => self.visit_const_expr(length),
258+
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id),
292259
TyKind::ImplTrait(..) => {
293260
self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span);
294261
}
295-
TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
296262
_ => {}
297263
}
298264
visit::walk_ty(self, ty);
299265
}
300266

301267
fn visit_stmt(&mut self, stmt: &'a Stmt) {
302268
match stmt.node {
303-
StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false),
269+
StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id),
304270
_ => visit::walk_stmt(self, stmt),
305271
}
306272
}
@@ -310,7 +276,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
310276
match nt.0 {
311277
token::NtExpr(ref expr) => {
312278
if let ExprKind::Mac(..) = expr.node {
313-
self.visit_macro_invoc(expr.id, false);
279+
self.visit_macro_invoc(expr.id);
314280
}
315281
}
316282
_ => {}

0 commit comments

Comments
 (0)