Skip to content

Commit ea47178

Browse files
committed
Fix anon const def-creation when macros are involved
1 parent d2b5aa6 commit ea47178

File tree

6 files changed

+166
-58
lines changed

6 files changed

+166
-58
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,14 +1188,7 @@ impl Expr {
11881188
///
11891189
/// Does not ensure that the path resolves to a const param, the caller should check this.
11901190
pub fn is_potential_trivial_const_arg(&self) -> bool {
1191-
let this = if let ExprKind::Block(block, None) = &self.kind
1192-
&& let [stmt] = block.stmts.as_slice()
1193-
&& let StmtKind::Expr(expr) = &stmt.kind
1194-
{
1195-
expr
1196-
} else {
1197-
self
1198-
};
1191+
let this = self.maybe_unwrap_block();
11991192

12001193
if let ExprKind::Path(None, path) = &this.kind
12011194
&& path.is_potential_trivial_const_arg()
@@ -1206,6 +1199,17 @@ impl Expr {
12061199
}
12071200
}
12081201

1202+
pub fn maybe_unwrap_block(&self) -> &Expr {
1203+
if let ExprKind::Block(block, None) = &self.kind
1204+
&& let [stmt] = block.stmts.as_slice()
1205+
&& let StmtKind::Expr(expr) = &stmt.kind
1206+
{
1207+
expr
1208+
} else {
1209+
self
1210+
}
1211+
}
1212+
12091213
pub fn to_bound(&self) -> Option<GenericBound> {
12101214
match &self.kind {
12111215
ExprKind::Path(None, path) => Some(GenericBound::Trait(

compiler/rustc_resolve/src/def_collector.rs

Lines changed: 107 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,33 @@ use rustc_hir::def_id::LocalDefId;
99
use rustc_span::hygiene::LocalExpnId;
1010
use rustc_span::symbol::{kw, sym, Symbol};
1111
use rustc_span::Span;
12-
use tracing::debug;
12+
use tracing::{debug, instrument};
1313

14-
use crate::{ImplTraitContext, Resolver};
14+
use crate::{ImplTraitContext, PendingAnonConstInfo, Resolver};
1515

1616
pub(crate) fn collect_definitions(
1717
resolver: &mut Resolver<'_, '_>,
1818
fragment: &AstFragment,
1919
expansion: LocalExpnId,
2020
) {
21-
let (parent_def, impl_trait_context, in_attr) = resolver.invocation_parents[&expansion];
22-
let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr };
21+
let (parent_def, pending_anon_const_info, impl_trait_context, in_attr) =
22+
resolver.invocation_parents[&expansion];
23+
let mut visitor = DefCollector {
24+
resolver,
25+
parent_def,
26+
pending_anon_const_info,
27+
expansion,
28+
impl_trait_context,
29+
in_attr,
30+
};
2331
fragment.visit_with(&mut visitor);
2432
}
2533

2634
/// Creates `DefId`s for nodes in the AST.
2735
struct DefCollector<'a, 'b, 'tcx> {
2836
resolver: &'a mut Resolver<'b, 'tcx>,
2937
parent_def: LocalDefId,
38+
pending_anon_const_info: Option<PendingAnonConstInfo>,
3039
impl_trait_context: ImplTraitContext,
3140
in_attr: bool,
3241
expansion: LocalExpnId,
@@ -41,6 +50,17 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
4150
span: Span,
4251
) -> LocalDefId {
4352
let parent_def = self.parent_def;
53+
self.create_def_with_parent(parent_def, node_id, name, def_kind, span)
54+
}
55+
56+
fn create_def_with_parent(
57+
&mut self,
58+
parent_def: LocalDefId,
59+
node_id: NodeId,
60+
name: Symbol,
61+
def_kind: DefKind,
62+
span: Span,
63+
) -> LocalDefId {
4464
debug!(
4565
"create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
4666
node_id, def_kind, parent_def
@@ -110,10 +130,11 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> {
110130

111131
fn visit_macro_invoc(&mut self, id: NodeId) {
112132
let id = id.placeholder_to_expn_id();
113-
let old_parent = self
114-
.resolver
115-
.invocation_parents
116-
.insert(id, (self.parent_def, self.impl_trait_context, self.in_attr));
133+
let pending_anon_const_info = self.pending_anon_const_info.take();
134+
let old_parent = self.resolver.invocation_parents.insert(
135+
id,
136+
(self.parent_def, pending_anon_const_info, self.impl_trait_context, self.in_attr),
137+
);
117138
assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
118139
}
119140
}
@@ -313,65 +334,104 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
313334
}
314335
}
315336

337+
#[instrument(level = "debug", skip(self))]
316338
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
317339
// HACK(min_generic_const_args): don't create defs for anon consts if we think they will
318340
// later be turned into ConstArgKind::Path's. because this is before resolve is done, we
319341
// may accidentally identify a construction of a unit struct as a param and not create a
320342
// def. we'll then create a def later in ast lowering in this case. the parent of nested
321343
// items will be messed up, but that's ok because there can't be any if we're just looking
322344
// for bare idents.
323-
if constant.value.is_potential_trivial_const_arg() {
345+
if matches!(constant.value.maybe_unwrap_block().kind, ExprKind::MacCall(..)) {
346+
debug!("ATTN(strict): unwrapped const is macro");
347+
self.pending_anon_const_info = Some(PendingAnonConstInfo {
348+
parent_def: self.parent_def,
349+
id: constant.id,
350+
span: constant.value.span,
351+
});
352+
visit::walk_anon_const(self, constant)
353+
} else if constant.value.is_potential_trivial_const_arg() {
354+
debug!("ATTN(strict): unwrapped const is potentially trivial");
324355
visit::walk_anon_const(self, constant)
325356
} else {
357+
debug!("ATTN(strict): unwrapped const is not trivial");
326358
let def =
327359
self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
328360
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
329361
}
330362
}
331363

332364
fn visit_expr(&mut self, expr: &'a Expr) {
333-
let parent_def = match expr.kind {
334-
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
335-
ExprKind::Closure(ref closure) => {
336-
// Async closures desugar to closures inside of closures, so
337-
// we must create two defs.
338-
let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
339-
match closure.coroutine_kind {
340-
Some(coroutine_kind) => {
341-
self.with_parent(closure_def, |this| {
342-
let coroutine_def = this.create_def(
343-
coroutine_kind.closure_id(),
344-
kw::Empty,
345-
DefKind::Closure,
346-
expr.span,
347-
);
348-
this.with_parent(coroutine_def, |this| visit::walk_expr(this, expr));
349-
});
350-
return;
351-
}
352-
None => closure_def,
353-
}
354-
}
355-
ExprKind::Gen(_, _, _, _) => {
356-
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
357-
}
358-
ExprKind::ConstBlock(ref constant) => {
359-
for attr in &expr.attrs {
360-
visit::walk_attribute(self, attr);
361-
}
362-
let def = self.create_def(
363-
constant.id,
365+
if matches!(expr.kind, ExprKind::MacCall(..)) {
366+
return self.visit_macro_invoc(expr.id);
367+
}
368+
369+
let grandparent_def = if let Some(pending_anon) = self.pending_anon_const_info {
370+
debug!("ATTN(lazy): pending anon={pending_anon:?} expr={expr:?}");
371+
self.pending_anon_const_info = None;
372+
if !expr.is_potential_trivial_const_arg() {
373+
debug!("ATTN(lazy): pending anon is not trivial");
374+
self.create_def_with_parent(
375+
pending_anon.parent_def,
376+
pending_anon.id,
364377
kw::Empty,
365-
DefKind::InlineConst,
366-
constant.value.span,
367-
);
368-
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
369-
return;
378+
DefKind::AnonConst,
379+
pending_anon.span,
380+
)
381+
} else {
382+
debug!("ATTN(lazy): pending anon is potentially trivial");
383+
self.parent_def
370384
}
371-
_ => self.parent_def,
385+
} else {
386+
self.parent_def
372387
};
373388

374-
self.with_parent(parent_def, |this| visit::walk_expr(this, expr));
389+
self.with_parent(grandparent_def, |this| {
390+
let parent_def = match expr.kind {
391+
ExprKind::Closure(ref closure) => {
392+
// Async closures desugar to closures inside of closures, so
393+
// we must create two defs.
394+
let closure_def =
395+
this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
396+
match closure.coroutine_kind {
397+
Some(coroutine_kind) => {
398+
this.with_parent(closure_def, |this| {
399+
let coroutine_def = this.create_def(
400+
coroutine_kind.closure_id(),
401+
kw::Empty,
402+
DefKind::Closure,
403+
expr.span,
404+
);
405+
this.with_parent(coroutine_def, |this| {
406+
visit::walk_expr(this, expr)
407+
});
408+
});
409+
return;
410+
}
411+
None => closure_def,
412+
}
413+
}
414+
ExprKind::Gen(_, _, _, _) => {
415+
this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
416+
}
417+
ExprKind::ConstBlock(ref constant) => {
418+
for attr in &expr.attrs {
419+
visit::walk_attribute(this, attr);
420+
}
421+
let def = this.create_def(
422+
constant.id,
423+
kw::Empty,
424+
DefKind::InlineConst,
425+
constant.value.span,
426+
);
427+
this.with_parent(def, |this| visit::walk_anon_const(this, constant));
428+
return;
429+
}
430+
_ => this.parent_def,
431+
};
432+
433+
this.with_parent(parent_def, |this| visit::walk_expr(this, expr))
434+
})
375435
}
376436

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

compiler/rustc_resolve/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ impl<'a> ParentScope<'a> {
170170
}
171171
}
172172

173+
#[derive(Copy, Debug, Clone)]
174+
struct PendingAnonConstInfo {
175+
parent_def: LocalDefId,
176+
id: NodeId,
177+
span: Span,
178+
}
179+
173180
#[derive(Copy, Debug, Clone)]
174181
enum ImplTraitContext {
175182
Existential,
@@ -1143,7 +1150,10 @@ pub struct Resolver<'a, 'tcx> {
11431150
/// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
11441151
/// we know what parent node that fragment should be attached to thanks to this table,
11451152
/// and how the `impl Trait` fragments were introduced.
1146-
invocation_parents: FxHashMap<LocalExpnId, (LocalDefId, ImplTraitContext, bool /*in_attr*/)>,
1153+
invocation_parents: FxHashMap<
1154+
LocalExpnId,
1155+
(LocalDefId, Option<PendingAnonConstInfo>, ImplTraitContext, bool /*in_attr*/),
1156+
>,
11471157

11481158
/// Some way to know that we are in a *trait* impl in `visit_assoc_item`.
11491159
/// FIXME: Replace with a more general AST map (together with some other fields).
@@ -1381,7 +1391,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13811391

13821392
let mut invocation_parents = FxHashMap::default();
13831393
invocation_parents
1384-
.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential, false));
1394+
.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, None, ImplTraitContext::Existential, false));
13851395

13861396
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = tcx
13871397
.sess

compiler/rustc_resolve/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
303303
.invocation_parents
304304
.get(&invoc_id)
305305
.or_else(|| self.invocation_parents.get(&eager_expansion_root))
306-
.filter(|&&(mod_def_id, _, in_attr)| {
306+
.filter(|&&(mod_def_id, _, _, in_attr)| {
307307
in_attr
308308
&& invoc.fragment_kind == AstFragmentKind::Expr
309309
&& self.tcx.def_kind(mod_def_id) == DefKind::Mod
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
3+
macro_rules! len_inner {
4+
() => {
5+
BAR
6+
};
7+
}
8+
9+
macro_rules! len {
10+
() => {
11+
len_inner!()
12+
};
13+
}
14+
15+
const BAR: usize = 0;
16+
17+
fn main() {
18+
let val: [bool; len!()] = [];
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ check-pass
2+
3+
// This is a regression test for #128016.
4+
5+
macro_rules! len {
6+
() => {
7+
BAR
8+
};
9+
}
10+
11+
const BAR: usize = 0;
12+
13+
fn main() {
14+
let val: [bool; len!()] = [];
15+
}

0 commit comments

Comments
 (0)