Rollup merge of #124488 - est31:arbitrary_expressions_error, r=pnkfelix

Add a note to the ArbitraryExpressionInPattern error

The current "arbitrary expressions aren't allowed in patterns" error is confusing, as it fires for code where it *looks* like a pattern but the compiler still treats it as an expression. That this is due to the `:expr` fragment specifier forcing the expression-ness property on the code.

In the test suite, the "arbitrary expressions aren't allowed in patterns" error can only be found in combination with macro_rules macros that force expression-ness of their content, namely via `:expr` metavariables. I also can't come up with cases where there would be an expression instead of a pattern, so I think it's always coming from an `:expr`.

In order to make the error less confusing, this adds a note explaining the weird `:expr` fragment behaviour.

Fixes #99380
This commit is contained in:
Matthias Krüger 2024-04-29 22:37:51 +02:00 committed by GitHub
commit 42ab090be9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 39 additions and 1 deletions

View File

@ -5,6 +5,7 @@ ast_lowering_abi_specified_multiple_times =
ast_lowering_arbitrary_expression_in_pattern =
arbitrary expressions aren't allowed in patterns
.pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression
ast_lowering_argument = argument

View File

@ -368,6 +368,8 @@ pub struct NeverPatternWithGuard {
pub struct ArbitraryExpressionInPattern {
#[primary_span]
pub span: Span,
#[note(ast_lowering_pattern_from_macro_note)]
pub pattern_from_macro_note: bool,
}
#[derive(Diagnostic)]

View File

@ -339,7 +339,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ExprKind::Path(..) if allow_paths => {}
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
_ => {
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern { span: expr.span });
let pattern_from_macro = expr.is_approximately_pattern();
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
span: expr.span,
pattern_from_macro_note: pattern_from_macro,
});
return self.arena.alloc(self.expr_err(expr.span, guar));
}
}

View File

@ -3,12 +3,16 @@ error: arbitrary expressions aren't allowed in patterns
|
LL | m!(y);
| ^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
error: arbitrary expressions aren't allowed in patterns
--> $DIR/issue-43250.rs:11:8
|
LL | m!(C);
| ^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
error: aborting due to 2 previous errors

View File

@ -0,0 +1,11 @@
macro_rules! foo {
($p:expr) => {
if let $p = Some(42) {
return;
}
};
}
fn main() {
foo!(Some(3)); //~ ERROR arbitrary expressions aren't allowed in patterns
}

View File

@ -0,0 +1,10 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/expr-in-pat-issue-99380.rs:10:10
|
LL | foo!(Some(3));
| ^^^^^^^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
error: aborting due to 1 previous error

View File

@ -4,6 +4,7 @@ error: arbitrary expressions aren't allowed in patterns
LL | Some(vec![43]) => {}
| ^^^^^^^^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error

View File

@ -9,6 +9,8 @@ error: arbitrary expressions aren't allowed in patterns
|
LL | funny!(a, a);
| ^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
error: aborting due to 2 previous errors

View File

@ -7,6 +7,7 @@ LL | () => { force_expr!(Vec::new()) }
LL | assert!(matches!(x, En::A(make_vec!())));
| ----------- in this macro invocation
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `make_vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: arbitrary expressions aren't allowed in patterns
@ -18,6 +19,7 @@ LL | () => { force_pat!(get_usize(), get_usize()) }
LL | assert!(matches!(5, make_pat!()));
| ----------- in this macro invocation
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info)
error: arbitrary expressions aren't allowed in patterns
@ -29,6 +31,7 @@ LL | () => { force_pat!(get_usize(), get_usize()) }
LL | assert!(matches!(5, make_pat!()));
| ----------- in this macro invocation
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors