Skip to content

def_collector: rework trivial const-arg handling #133455

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1187,14 +1187,15 @@ pub struct Expr {
}

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

if let ExprKind::Path(None, path) = &this.kind
&& path.is_potential_trivial_const_arg()
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id();
// HACK(min_generic_const_args): see lower_anon_const
if !expr.is_potential_trivial_const_arg(true) {
if !expr.is_potential_trivial_const_arg() {
self.create_def(
parent_def_id,
node_id,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let node_id = self.next_node_id();

// HACK(min_generic_const_args): see lower_anon_const
if !arg.is_potential_trivial_const_arg(true) {
if !arg.is_potential_trivial_const_arg() {
// Add a definition for the in-band const def.
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
}
Expand Down
37 changes: 24 additions & 13 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
def_id
}

// HACK: See `DefCollector::handle_lazy_anon_const_def` for why this is necessary.
fn create_or_reuse_anon_const_def(
&mut self,
parent: LocalDefId,
node_id: ast::NodeId,
name: Symbol,
def_kind: DefKind,
span: Span,
) -> LocalDefId {
debug_assert_eq!(def_kind, DefKind::AnonConst);
if let Some(def_id) = self.opt_local_def_id(node_id) {
def_id
} else {
self.create_def(parent, node_id, name, def_kind, span)
}
}

fn next_node_id(&mut self) -> NodeId {
let start = self.resolver.next_node_id;
let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
Expand Down Expand Up @@ -2181,19 +2198,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// See [`hir::ConstArg`] for when to use this function vs
/// [`Self::lower_anon_const_to_const_arg`].
fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
if c.value.is_potential_trivial_const_arg(true) {
// HACK(min_generic_const_args): see DefCollector::visit_anon_const
// Over there, we guess if this is a bare param and only create a def if
// we think it's not. However we may can guess wrong (see there for example)
// in which case we have to create the def here.
self.create_def(
self.current_def_id_parent,
c.id,
kw::Empty,
DefKind::AnonConst,
c.value.span,
);
}
self.create_or_reuse_anon_const_def(
self.current_def_id_parent,
c.id,
kw::Empty,
DefKind::AnonConst,
c.value.span,
);

self.arena.alloc(self.with_new_scopes(c.value.span, |this| {
let def_id = this.local_def_id(c.id);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
if self.cx.sess.opts.incremental.is_some() {
for (invoc, _) in invocations.iter_mut() {
let expn_id = invoc.expansion_data.id;
// When lowering anon-consts, we may end up with spans whose
// parent is the containing item instead of the anon-const itself.
// See `DefCollector::handle_lazy_anon_const_def` for more details.
//
// FIXME(lcnr): I believe that this shouldn't cause any issues wrt to
// incremental compilation, but am not 100% confident.
let parent_def = self.cx.resolver.invocation_parent(expn_id);
Copy link
Contributor Author

@lcnr lcnr Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an existing concern. would accept this as is for now and handle it in case it is problematic

I looked a bit into ways to make this more resilient but gave up on that for now. If there's any affected code which is not covered by the existing tests, I'll look into this at that point.

let span = invoc.span_mut();
*span = span.with_parent(Some(parent_def));
Expand Down
Loading
Loading