Skip to content

Commit

Permalink
Check for both StmtKind::MacCall and ExprKind::MacCall
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxyUwU committed Nov 5, 2024
1 parent 096277e commit 1d6e847
Show file tree
Hide file tree
Showing 6 changed files with 466 additions and 36 deletions.
35 changes: 31 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@ impl Expr {
///
/// 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().1 } else { self };
let this = if strip_identity_block { self.maybe_unwrap_block() } else { self };

if let ExprKind::Path(None, path) = &this.kind
&& path.is_potential_trivial_const_arg()
Expand All @@ -1206,14 +1206,41 @@ impl Expr {
}

/// Returns an expression with (when possible) *one* outter brace removed
pub fn maybe_unwrap_block(&self) -> (bool, &Expr) {
pub fn maybe_unwrap_block(&self) -> &Expr {
if let ExprKind::Block(block, None) = &self.kind
&& let [stmt] = block.stmts.as_slice()
&& let StmtKind::Expr(expr) = &stmt.kind
{
(true, expr)
expr
} else {
(false, self)
self
}
}

/// Determines whether this expression is a macro call optionally wrapped in braces . If
/// `already_stripped_block` is set then we do not attempt to peel off a layer of braces.
///
/// Returns the [`NodeId`] of the macro call and whether a layer of braces has been peeled
/// either before, or part of, this function.
pub fn optionally_braced_mac_call(
&self,
already_stripped_block: bool,
) -> Option<(bool, NodeId)> {
match &self.kind {
ExprKind::Block(block, None)
if let [stmt] = &*block.stmts
&& !already_stripped_block =>
{
match &stmt.kind {
StmtKind::MacCall(_) => Some((true, stmt.id)),
StmtKind::Expr(expr) if let ExprKind::MacCall(_) = &expr.kind => {
Some((true, expr.id))
}
_ => None,
}
}
ExprKind::MacCall(_) => Some((already_stripped_block, self.id)),
_ => None,
}
}

Expand Down
29 changes: 10 additions & 19 deletions compiler/rustc_resolve/src/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,16 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
&self,
anon_const: &'a AnonConst,
) -> Option<(PendingAnonConstInfo, NodeId)> {
let (block_was_stripped, expr) = anon_const.value.maybe_unwrap_block();
match expr {
Expr { kind: ExprKind::MacCall(..), id, .. } => Some((
anon_const.value.optionally_braced_mac_call(false).map(|(block_was_stripped, id)| {
(
PendingAnonConstInfo {
id: anon_const.id,
span: anon_const.value.span,
block_was_stripped,
},
*id,
)),
_ => None,
}
id,
)
})
}

/// Determines whether the expression `const_arg_sub_expr` is a simple macro call, sometimes
Expand All @@ -161,18 +159,11 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
panic!("Checking expr is trivial macro call without having entered anon const: `{const_arg_sub_expr:?}`"),
);

let (block_was_stripped, expr) = if pending_anon.block_was_stripped {
(true, const_arg_sub_expr)
} else {
const_arg_sub_expr.maybe_unwrap_block()
};

match expr {
Expr { kind: ExprKind::MacCall(..), id, .. } => {
Some((PendingAnonConstInfo { block_was_stripped, ..pending_anon }, *id))
}
_ => None,
}
const_arg_sub_expr.optionally_braced_mac_call(pending_anon.block_was_stripped).map(
|(block_was_stripped, id)| {
(PendingAnonConstInfo { block_was_stripped, ..pending_anon }, id)
},
)
}
}

Expand Down
13 changes: 0 additions & 13 deletions tests/crashes/131915.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Regression test for #131915 where we did not handle macro calls as
// statements correctly when determining if a const argument should
// have a `DefId` created or not.

macro_rules! y {
( $($matcher:tt)*) => {
x
//~^ ERROR: cannot find value `x` in this scope
};
}

const _: A<
//~^ ERROR: free constant item without body
//~| ERROR: cannot find type `A` in this scope
{
y! { test.tou8 }
},
>;

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
error: free constant item without body
--> $DIR/const_arg_trivial_macro_expansion-2.rs:12:1
|
LL | / const _: A<
LL | |
LL | |
LL | | {
LL | | y! { test.tou8 }
LL | | },
LL | | >;
| | ^ help: provide a definition for the constant: `= <expr>;`
| |__|
|

error[E0412]: cannot find type `A` in this scope
--> $DIR/const_arg_trivial_macro_expansion-2.rs:12:10
|
LL | const _: A<
| ^ not found in this scope

error[E0425]: cannot find value `x` in this scope
--> $DIR/const_arg_trivial_macro_expansion-2.rs:7:9
|
LL | x
| ^ not found in this scope
...
LL | y! { test.tou8 }
| ---------------- in this macro invocation
|
= note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you might be missing a const parameter
|
LL | const _<const x: /* Type */>: A<
| +++++++++++++++++++++

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0412, E0425.
For more information about an error, try `rustc --explain E0412`.
Loading

0 comments on commit 1d6e847

Please sign in to comment.