Skip to content

Commit 93e188c

Browse files
committed
always create DefIds when lowering anon-consts
1 parent b3c77b8 commit 93e188c

File tree

9 files changed

+58
-185
lines changed

9 files changed

+58
-185
lines changed

compiler/rustc_ast/src/ast.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1187,14 +1187,15 @@ pub struct Expr {
11871187
}
11881188

11891189
impl Expr {
1190-
/// Is this expr either `N`, or `{ N }`.
1190+
/// Could this expr be either `N`, or `{ N }`, where `N` is a const parameter.
11911191
///
11921192
/// If this is not the case, name resolution does not resolve `N` when using
11931193
/// `min_const_generics` as more complex expressions are not supported.
11941194
///
11951195
/// Does not ensure that the path resolves to a const param, the caller should check this.
1196-
pub fn is_potential_trivial_const_arg(&self, strip_identity_block: bool) -> bool {
1197-
let this = if strip_identity_block { self.maybe_unwrap_block() } else { self };
1196+
/// This also does not consider macros, so it's only correct after macro-expansion.
1197+
pub fn is_potential_trivial_const_arg(&self) -> bool {
1198+
let this = self.maybe_unwrap_block();
11981199

11991200
if let ExprKind::Path(None, path) = &this.kind
12001201
&& path.is_potential_trivial_const_arg()

compiler/rustc_ast_lowering/src/asm.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
222222
// Wrap the expression in an AnonConst.
223223
let parent_def_id = self.current_def_id_parent;
224224
let node_id = self.next_node_id();
225-
// HACK(min_generic_const_args): see lower_anon_const
226-
if !expr.is_potential_trivial_const_arg(true) {
227-
self.create_def(
228-
parent_def_id,
229-
node_id,
230-
kw::Empty,
231-
DefKind::AnonConst,
232-
*op_sp,
233-
);
234-
}
225+
self.create_def(
226+
parent_def_id,
227+
node_id,
228+
kw::Empty,
229+
DefKind::AnonConst,
230+
*op_sp,
231+
);
235232
let anon_const = AnonConst { id: node_id, value: P(expr) };
236233
hir::InlineAsmOperand::SymFn {
237234
anon_const: self.lower_anon_const_to_anon_const(&anon_const),

compiler/rustc_ast_lowering/src/expr.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -454,13 +454,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
454454
if legacy_args_idx.contains(&idx) {
455455
let parent_def_id = self.current_def_id_parent;
456456
let node_id = self.next_node_id();
457-
458-
// HACK(min_generic_const_args): see lower_anon_const
459-
if !arg.is_potential_trivial_const_arg(true) {
460-
// Add a definition for the in-band const def.
461-
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
462-
}
463-
457+
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
464458
let mut visitor = WillCreateDefIdsVisitor {};
465459
let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
466460
AstP(Expr {

compiler/rustc_ast_lowering/src/lib.rs

+1-15
Original file line numberDiff line numberDiff line change
@@ -2164,7 +2164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21642164
);
21652165

21662166
return ConstArg {
2167-
hir_id: self.next_id(),
2167+
hir_id: self.lower_node_id(anon.id),
21682168
kind: hir::ConstArgKind::Path(qpath),
21692169
is_desugared_from_effects: false,
21702170
};
@@ -2181,20 +2181,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21812181
/// See [`hir::ConstArg`] for when to use this function vs
21822182
/// [`Self::lower_anon_const_to_const_arg`].
21832183
fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
2184-
if c.value.is_potential_trivial_const_arg(true) {
2185-
// HACK(min_generic_const_args): see DefCollector::visit_anon_const
2186-
// Over there, we guess if this is a bare param and only create a def if
2187-
// we think it's not. However we may can guess wrong (see there for example)
2188-
// in which case we have to create the def here.
2189-
self.create_def(
2190-
self.current_def_id_parent,
2191-
c.id,
2192-
kw::Empty,
2193-
DefKind::AnonConst,
2194-
c.value.span,
2195-
);
2196-
}
2197-
21982184
self.arena.alloc(self.with_new_scopes(c.value.span, |this| {
21992185
let def_id = this.local_def_id(c.id);
22002186
let hir_id = this.lower_node_id(c.id);

compiler/rustc_metadata/src/rmeta/encoder.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
13831383
let def_id = local_id.to_def_id();
13841384
let def_kind = tcx.def_kind(local_id);
13851385
self.tables.def_kind.set_some(def_id.index, def_kind);
1386+
1387+
// The `DefCollector` will sometimes create unnecessary `DefId`s
1388+
// for trivial const arguments which are directly lowered to
1389+
// `ConstArgKind::Path`. We never actually access this `DefId`
1390+
// anywhere so we don't need to encode it for other crates.
1391+
if def_kind == DefKind::AnonConst
1392+
&& matches!(
1393+
tcx.hir_node_by_def_id(local_id),
1394+
hir::Node::ConstArg(hir::ConstArg { kind: hir::ConstArgKind::Path(..), .. })
1395+
)
1396+
{
1397+
continue;
1398+
}
1399+
13861400
if should_encode_span(def_kind) {
13871401
let def_span = tcx.def_span(local_id);
13881402
record!(self.tables.def_span[def_id] <- def_span);

compiler/rustc_resolve/src/def_collector.rs

+26-132
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,23 @@ use rustc_span::hygiene::LocalExpnId;
1212
use rustc_span::symbol::{Symbol, kw, sym};
1313
use tracing::debug;
1414

15-
use crate::{ImplTraitContext, InvocationParent, PendingAnonConstInfo, Resolver};
15+
use crate::{ImplTraitContext, InvocationParent, Resolver};
1616

1717
pub(crate) fn collect_definitions(
1818
resolver: &mut Resolver<'_, '_>,
1919
fragment: &AstFragment,
2020
expansion: LocalExpnId,
2121
) {
22-
let InvocationParent { parent_def, pending_anon_const_info, impl_trait_context, in_attr } =
22+
let InvocationParent { parent_def, impl_trait_context, in_attr } =
2323
resolver.invocation_parents[&expansion];
24-
let mut visitor = DefCollector {
25-
resolver,
26-
parent_def,
27-
pending_anon_const_info,
28-
expansion,
29-
impl_trait_context,
30-
in_attr,
31-
};
24+
let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr };
3225
fragment.visit_with(&mut visitor);
3326
}
3427

3528
/// Creates `DefId`s for nodes in the AST.
3629
struct DefCollector<'a, 'ra, 'tcx> {
3730
resolver: &'a mut Resolver<'ra, 'tcx>,
3831
parent_def: LocalDefId,
39-
/// If we have an anon const that consists of a macro invocation, e.g. `Foo<{ m!() }>`,
40-
/// we need to wait until we know what the macro expands to before we create the def for
41-
/// the anon const. That's because we lower some anon consts into `hir::ConstArgKind::Path`,
42-
/// which don't have defs.
43-
///
44-
/// See `Self::visit_anon_const()`.
45-
pending_anon_const_info: Option<PendingAnonConstInfo>,
4632
impl_trait_context: ImplTraitContext,
4733
in_attr: bool,
4834
expansion: LocalExpnId,
@@ -110,61 +96,13 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
11096

11197
fn visit_macro_invoc(&mut self, id: NodeId) {
11298
let id = id.placeholder_to_expn_id();
113-
let pending_anon_const_info = self.pending_anon_const_info.take();
11499
let old_parent = self.resolver.invocation_parents.insert(id, InvocationParent {
115100
parent_def: self.parent_def,
116-
pending_anon_const_info,
117101
impl_trait_context: self.impl_trait_context,
118102
in_attr: self.in_attr,
119103
});
120104
assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
121105
}
122-
123-
/// Determines whether the const argument `AnonConst` is a simple macro call, optionally
124-
/// surrounded with braces.
125-
///
126-
/// If this const argument *is* a trivial macro call then the id for the macro call is
127-
/// returned along with the information required to build the anon const's def if
128-
/// the macro call expands to a non-trivial expression.
129-
fn is_const_arg_trivial_macro_expansion(
130-
&self,
131-
anon_const: &'a AnonConst,
132-
) -> Option<(PendingAnonConstInfo, NodeId)> {
133-
anon_const.value.optionally_braced_mac_call(false).map(|(block_was_stripped, id)| {
134-
(
135-
PendingAnonConstInfo {
136-
id: anon_const.id,
137-
span: anon_const.value.span,
138-
block_was_stripped,
139-
},
140-
id,
141-
)
142-
})
143-
}
144-
145-
/// Determines whether the expression `const_arg_sub_expr` is a simple macro call, sometimes
146-
/// surrounded with braces if a set of braces has not already been entered. This is required
147-
/// as `{ N }` is treated as equivalent to a bare parameter `N` whereas `{{ N }}` is treated as
148-
/// a real block expression and is lowered to an anonymous constant which is not allowed to use
149-
/// generic parameters.
150-
///
151-
/// If this expression is a trivial macro call then the id for the macro call is
152-
/// returned along with the information required to build the anon const's def if
153-
/// the macro call expands to a non-trivial expression.
154-
fn is_const_arg_sub_expr_trivial_macro_expansion(
155-
&self,
156-
const_arg_sub_expr: &'a Expr,
157-
) -> Option<(PendingAnonConstInfo, NodeId)> {
158-
let pending_anon = self.pending_anon_const_info.unwrap_or_else(||
159-
panic!("Checking expr is trivial macro call without having entered anon const: `{const_arg_sub_expr:?}`"),
160-
);
161-
162-
const_arg_sub_expr.optionally_braced_mac_call(pending_anon.block_was_stripped).map(
163-
|(block_was_stripped, id)| {
164-
(PendingAnonConstInfo { block_was_stripped, ..pending_anon }, id)
165-
},
166-
)
167-
}
168106
}
169107

170108
impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
@@ -376,78 +314,34 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
376314
}
377315

378316
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
379-
// HACK(min_generic_const_args): don't create defs for anon consts if we think they will
380-
// later be turned into ConstArgKind::Path's. because this is before resolve is done, we
381-
// may accidentally identify a construction of a unit struct as a param and not create a
382-
// def. we'll then create a def later in ast lowering in this case. the parent of nested
383-
// items will be messed up, but that's ok because there can't be any if we're just looking
384-
// for bare idents.
385-
386-
if let Some((pending_anon, macro_invoc)) =
387-
self.is_const_arg_trivial_macro_expansion(constant)
388-
{
389-
self.pending_anon_const_info = Some(pending_anon);
390-
return self.visit_macro_invoc(macro_invoc);
391-
} else if constant.value.is_potential_trivial_const_arg(true) {
392-
return visit::walk_anon_const(self, constant);
393-
}
394-
395-
let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
396-
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
317+
let parent =
318+
self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
319+
self.with_parent(parent, |this| visit::walk_anon_const(this, constant));
397320
}
398321

399322
fn visit_expr(&mut self, expr: &'a Expr) {
400-
// If we're visiting the expression of a const argument that was a macro call then
401-
// check if it is *still* unknown whether it is a trivial const arg or not. If so
402-
// recurse into the macro call and delay creating the anon const def until expansion.
403-
if self.pending_anon_const_info.is_some()
404-
&& let Some((pending_anon, macro_invoc)) =
405-
self.is_const_arg_sub_expr_trivial_macro_expansion(expr)
406-
{
407-
self.pending_anon_const_info = Some(pending_anon);
408-
return self.visit_macro_invoc(macro_invoc);
409-
}
410-
411-
// See self.pending_anon_const_info for explanation
412-
let parent_def = self
413-
.pending_anon_const_info
414-
.take()
415-
// If we already stripped away a set of braces then do not do it again when determining
416-
// if the macro expanded to a trivial const arg. This arises in cases such as:
417-
// `Foo<{ bar!() }>` where `bar!()` expands to `{ N }`. This should not be considered a
418-
// trivial const argument even though `{ N }` by itself *is*.
419-
.filter(|pending_anon| {
420-
!expr.is_potential_trivial_const_arg(!pending_anon.block_was_stripped)
421-
})
422-
.map(|pending_anon| {
423-
self.create_def(pending_anon.id, kw::Empty, DefKind::AnonConst, pending_anon.span)
424-
})
425-
.unwrap_or(self.parent_def);
426-
427-
self.with_parent(parent_def, |this| {
428-
let parent_def = match expr.kind {
429-
ExprKind::MacCall(..) => return this.visit_macro_invoc(expr.id),
430-
ExprKind::Closure(..) | ExprKind::Gen(..) => {
431-
this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
432-
}
433-
ExprKind::ConstBlock(ref constant) => {
434-
for attr in &expr.attrs {
435-
visit::walk_attribute(this, attr);
436-
}
437-
let def = this.create_def(
438-
constant.id,
439-
kw::Empty,
440-
DefKind::InlineConst,
441-
constant.value.span,
442-
);
443-
this.with_parent(def, |this| visit::walk_anon_const(this, constant));
444-
return;
323+
let parent_def = match expr.kind {
324+
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
325+
ExprKind::Closure(..) | ExprKind::Gen(..) => {
326+
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
327+
}
328+
ExprKind::ConstBlock(ref constant) => {
329+
for attr in &expr.attrs {
330+
visit::walk_attribute(self, attr);
445331
}
446-
_ => this.parent_def,
447-
};
332+
let def = self.create_def(
333+
constant.id,
334+
kw::Empty,
335+
DefKind::InlineConst,
336+
constant.value.span,
337+
);
338+
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
339+
return;
340+
}
341+
_ => self.parent_def,
342+
};
448343

449-
this.with_parent(parent_def, |this| visit::walk_expr(this, expr))
450-
})
344+
self.with_parent(parent_def, |this| visit::walk_expr(this, expr))
451345
}
452346

453347
fn visit_ty(&mut self, ty: &'a Ty) {

compiler/rustc_resolve/src/late.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4522,7 +4522,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
45224522
);
45234523

45244524
self.resolve_anon_const_manual(
4525-
constant.value.is_potential_trivial_const_arg(true),
4525+
constant.value.is_potential_trivial_const_arg(),
45264526
anon_const_kind,
45274527
|this| this.resolve_expr(&constant.value, None),
45284528
)
@@ -4686,7 +4686,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
46864686
// that is how they will be later lowered to HIR.
46874687
if const_args.contains(&idx) {
46884688
self.resolve_anon_const_manual(
4689-
argument.is_potential_trivial_const_arg(true),
4689+
argument.is_potential_trivial_const_arg(),
46904690
AnonConstKind::ConstArg(IsRepeatExpr::No),
46914691
|this| this.resolve_expr(argument, None),
46924692
);

compiler/rustc_resolve/src/lib.rs

-13
Original file line numberDiff line numberDiff line change
@@ -174,31 +174,18 @@ impl<'ra> ParentScope<'ra> {
174174
#[derive(Copy, Debug, Clone)]
175175
struct InvocationParent {
176176
parent_def: LocalDefId,
177-
pending_anon_const_info: Option<PendingAnonConstInfo>,
178177
impl_trait_context: ImplTraitContext,
179178
in_attr: bool,
180179
}
181180

182181
impl InvocationParent {
183182
const ROOT: Self = Self {
184183
parent_def: CRATE_DEF_ID,
185-
pending_anon_const_info: None,
186184
impl_trait_context: ImplTraitContext::Existential,
187185
in_attr: false,
188186
};
189187
}
190188

191-
#[derive(Copy, Debug, Clone)]
192-
struct PendingAnonConstInfo {
193-
// A const arg is only a "trivial" const arg if it has at *most* one set of braces
194-
// around the argument. We track whether we have stripped an outter brace so that
195-
// if a macro expands to a braced expression *and* the macro was itself inside of
196-
// some braces then we can consider it to be a non-trivial const argument.
197-
block_was_stripped: bool,
198-
id: NodeId,
199-
span: Span,
200-
}
201-
202189
#[derive(Copy, Debug, Clone)]
203190
enum ImplTraitContext {
204191
Existential,

tests/ui/consts/issue-36163.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}`
1+
error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}`
22
--> $DIR/issue-36163.rs:4:9
33
|
44
LL | B = A,
55
| ^
66
|
7-
note: ...which requires const-evaluating + checking `Foo::{constant#0}`...
7+
note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`...
88
--> $DIR/issue-36163.rs:4:9
99
|
1010
LL | B = A,
@@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`...
1919
|
2020
LL | const A: isize = Foo::B as isize;
2121
| ^^^^^^^^^^^^^^^
22-
= note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle
22+
= note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
2323
note: cycle used when checking that `Foo` is well-formed
2424
--> $DIR/issue-36163.rs:3:1
2525
|

0 commit comments

Comments
 (0)