Skip to content

Commit a43257a

Browse files
committed
DefCollector stuff
1 parent 6a17f14 commit a43257a

File tree

4 files changed

+113
-56
lines changed

4 files changed

+113
-56
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,6 +2424,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24242424
self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField);
24252425

24262426
let expr = if let ExprKind::ConstBlock(anon_const) = &f.expr.kind {
2427+
let def_id = self.local_def_id(anon_const.id);
2428+
let def_kind = self.tcx.def_kind(def_id);
2429+
assert_eq!(DefKind::AnonConst, def_kind);
2430+
24272431
self.lower_anon_const_to_const_arg_direct(anon_const)
24282432
} else {
24292433
self.lower_expr_to_const_arg_direct(&f.expr)

compiler/rustc_resolve/src/def_collector.rs

Lines changed: 69 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@ use rustc_hir::def_id::LocalDefId;
1111
use rustc_middle::span_bug;
1212
use rustc_span::hygiene::LocalExpnId;
1313
use rustc_span::{Span, Symbol, sym};
14-
use tracing::debug;
14+
use tracing::{debug, instrument};
1515

16-
use crate::{ImplTraitContext, InvocationParent, Resolver};
16+
use crate::{ConstArgContext, ImplTraitContext, InvocationParent, Resolver};
1717

1818
pub(crate) fn collect_definitions(
1919
resolver: &mut Resolver<'_, '_>,
2020
fragment: &AstFragment,
2121
expansion: LocalExpnId,
2222
) {
2323
let invocation_parent = resolver.invocation_parents[&expansion];
24+
debug!("new fragment to visit with invocation_parent: {invocation_parent:?}");
2425
let mut visitor = DefCollector { resolver, expansion, invocation_parent };
2526
fragment.visit_with(&mut visitor);
2627
}
@@ -74,10 +75,10 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
7475
self.invocation_parent.impl_trait_context = orig_itc;
7576
}
7677

77-
fn with_direct_const_arg<F: FnOnce(&mut Self)>(&mut self, is_direct: bool, f: F) {
78-
let orig = mem::replace(&mut self.invocation_parent.in_direct_const_arg, is_direct);
78+
fn with_const_arg<F: FnOnce(&mut Self)>(&mut self, ctxt: ConstArgContext, f: F) {
79+
let orig = mem::replace(&mut self.invocation_parent.const_arg_context, ctxt);
7980
f(self);
80-
self.invocation_parent.in_direct_const_arg = orig;
81+
self.invocation_parent.const_arg_context = orig;
8182
}
8283

8384
fn collect_field(&mut self, field: &'a FieldDef, index: Option<usize>) {
@@ -99,7 +100,10 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
99100
}
100101
}
101102

103+
#[instrument(level = "debug", skip(self))]
102104
fn visit_macro_invoc(&mut self, id: NodeId) {
105+
debug!(?self.invocation_parent);
106+
103107
let id = id.placeholder_to_expn_id();
104108
let old_parent = self.resolver.invocation_parents.insert(id, self.invocation_parent);
105109
assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
@@ -363,73 +367,84 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
363367
}
364368

365369
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
366-
// `MgcaDisambiguation::Direct` is set even when MGCA is disabled, so
367-
// to avoid affecting stable we have to feature gate the not creating
368-
// anon consts
369-
if let MgcaDisambiguation::Direct = constant.mgca_disambiguation
370-
&& self.resolver.tcx.features().min_generic_const_args()
371-
{
372-
self.with_direct_const_arg(true, |this| {
370+
match constant.mgca_disambiguation {
371+
// `MgcaDisambiguation::Direct` is set even when MGCA is disabled, so
372+
// to avoid affecting stable we have to feature gate the not creating
373+
// anon consts
374+
_ if !self.resolver.tcx.features().min_generic_const_args() => {
375+
let parent =
376+
self.create_def(constant.id, None, DefKind::AnonConst, constant.value.span);
377+
self.with_parent(parent, |this| visit::walk_anon_const(this, constant));
378+
}
379+
MgcaDisambiguation::Direct => self.with_const_arg(ConstArgContext::Direct, |this| {
373380
visit::walk_anon_const(this, constant);
374-
});
375-
return;
376-
}
377-
378-
self.with_direct_const_arg(false, |this| {
379-
let parent =
380-
this.create_def(constant.id, None, DefKind::AnonConst, constant.value.span);
381-
this.with_parent(parent, |this| visit::walk_anon_const(this, constant));
382-
})
381+
}),
382+
MgcaDisambiguation::AnonConst => {
383+
self.with_const_arg(ConstArgContext::NonDirect, |this| {
384+
let parent =
385+
this.create_def(constant.id, None, DefKind::AnonConst, constant.value.span);
386+
this.with_parent(parent, |this| visit::walk_anon_const(this, constant));
387+
})
388+
}
389+
};
383390
}
384391

392+
#[instrument(level = "debug", skip(self))]
385393
fn visit_expr(&mut self, expr: &'a Expr) {
386-
let handle_const_block = |this: &mut Self, constant: &'a AnonConst, def_kind: DefKind| {
387-
for attr in &expr.attrs {
388-
visit::walk_attribute(this, attr);
389-
}
394+
debug!(?self.invocation_parent);
390395

391-
let def = this.create_def(constant.id, None, def_kind, constant.value.span);
392-
this.with_direct_const_arg(false, |this| {
393-
this.with_parent(def, |this| visit::walk_anon_const(this, constant));
394-
});
395-
};
396-
397-
let parent_def = match expr.kind {
396+
let parent_def = match &expr.kind {
398397
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
399398
ExprKind::Closure(..) | ExprKind::Gen(..) => {
400399
self.create_def(expr.id, None, DefKind::Closure, expr.span)
401400
}
402-
ExprKind::ConstBlock(ref constant) => {
403-
handle_const_block(self, constant, DefKind::InlineConst);
404-
return;
405-
}
406-
ExprKind::Struct(ref se) if self.invocation_parent.in_direct_const_arg => {
407-
let StructExpr { qself, path, fields, rest } = &**se;
408-
409-
for init_expr in fields {
410-
if let ExprKind::ConstBlock(ref constant) = init_expr.expr.kind {
411-
handle_const_block(self, constant, DefKind::AnonConst);
412-
} else {
413-
visit::walk_expr_field(self, init_expr);
401+
ExprKind::ConstBlock(constant) => {
402+
// Under `min_generic_const_args` a `const { }` block sometimes
403+
// corresponds to an anon const rather than an inline const.
404+
let def_kind = match self.invocation_parent.const_arg_context {
405+
ConstArgContext::Direct => DefKind::AnonConst,
406+
ConstArgContext::NonDirect => DefKind::InlineConst,
407+
};
408+
409+
return self.with_const_arg(ConstArgContext::NonDirect, |this| {
410+
for attr in &expr.attrs {
411+
visit::walk_attribute(this, attr);
414412
}
415-
}
416413

417-
if let Some(qself) = qself {
418-
self.visit_qself(qself);
414+
let def = this.create_def(constant.id, None, def_kind, constant.value.span);
415+
this.with_parent(def, |this| visit::walk_anon_const(this, constant));
416+
});
417+
}
418+
419+
// Avoid overwriting `const_arg_context` as we may want to treat const blocks
420+
// as being anon consts if we are inside a const argument.
421+
ExprKind::Struct(_) => return visit::walk_expr(self, expr),
422+
// FIXME(mgca): we may want to handle block labels in some manner
423+
ExprKind::Block(block, _) if let [stmt] = block.stmts.as_slice() => match stmt.kind {
424+
StmtKind::Let(..) | StmtKind::Item(..) | StmtKind::Semi(..) | StmtKind::Empty => {
425+
return self.with_const_arg(ConstArgContext::NonDirect, |this| {
426+
visit::walk_expr(this, expr)
427+
});
419428
}
420-
self.visit_path(path);
421429

422-
match rest {
423-
StructRest::Base(expr) => self.visit_expr(expr),
424-
_ => (),
430+
// FIXME(mgca): this probably means that mac calls that expand
431+
// to semi'd const blocks are handled differently to just writing
432+
// out a semi'd const block.
433+
StmtKind::Expr(..) | StmtKind::MacCall(..) => {
434+
return visit::walk_expr(self, expr);
425435
}
436+
},
426437

427-
return;
438+
_ => {
439+
return self.with_const_arg(ConstArgContext::NonDirect, |this| {
440+
visit::walk_expr(this, expr)
441+
});
428442
}
429-
_ => self.invocation_parent.parent_def,
430443
};
431444

432-
self.with_parent(parent_def, |this| visit::walk_expr(this, expr))
445+
self.with_const_arg(ConstArgContext::NonDirect, |this| {
446+
this.with_parent(parent_def, |this| visit::walk_expr(this, expr))
447+
})
433448
}
434449

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

compiler/rustc_resolve/src/lib.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ struct InvocationParent {
187187
parent_def: LocalDefId,
188188
impl_trait_context: ImplTraitContext,
189189
in_attr: bool,
190-
in_direct_const_arg: bool,
190+
const_arg_context: ConstArgContext,
191191
}
192192

193193
impl InvocationParent {
194194
const ROOT: Self = Self {
195195
parent_def: CRATE_DEF_ID,
196196
impl_trait_context: ImplTraitContext::Existential,
197197
in_attr: false,
198-
in_direct_const_arg: false,
198+
const_arg_context: ConstArgContext::NonDirect,
199199
};
200200
}
201201

@@ -206,6 +206,13 @@ enum ImplTraitContext {
206206
InBinding,
207207
}
208208

209+
#[derive(Copy, Clone, Debug)]
210+
enum ConstArgContext {
211+
Direct,
212+
/// Either inside of an `AnonConst` or not inside a const argument at all.
213+
NonDirect,
214+
}
215+
209216
/// Used for tracking import use types which will be used for redundant import checking.
210217
///
211218
/// ### Used::Scope Example
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ check-pass
2+
3+
// Test that the def collector makes `AnonConst`s not `InlineConst`s even
4+
// when the const block is obscured via macros.
5+
6+
#![feature(min_generic_const_args, adt_const_params)]
7+
#![expect(incomplete_features)]
8+
9+
macro_rules! const_block {
10+
($e:expr) => { const {
11+
$e
12+
} }
13+
}
14+
15+
macro_rules! foo_expr {
16+
($e:expr) => { Foo {
17+
field: $e,
18+
} }
19+
}
20+
21+
use std::marker::ConstParamTy;
22+
23+
#[derive(PartialEq, Eq, ConstParamTy)]
24+
struct Foo { field: u32 }
25+
26+
fn foo<const N: Foo>() {}
27+
28+
fn main() {
29+
foo::<{ Foo { field: const_block!{ 1 + 1 }} }>();
30+
foo::<{ foo_expr! { const_block! { 1 + 1 }} }>();
31+
}

0 commit comments

Comments
 (0)