Skip to content

Commit 74a18a0

Browse files
committed
Be more picky in parse_literal_maybe_minus.
By only accepting `NtExpr` if it's a literal (possibly with a unary minus). This means various error cases are caught during parsing, instead of during HIR lowering, and the `ArbitraryExpressionInPattern` error is no longer needed.
1 parent 494db01 commit 74a18a0

20 files changed

+109
-135
lines changed

compiler/rustc_ast_lowering/messages.ftl

-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ ast_lowering_abi_specified_multiple_times =
33
.label = previously specified here
44
.note = these ABIs are equivalent on the current target
55
6-
ast_lowering_arbitrary_expression_in_pattern =
7-
arbitrary expressions aren't allowed in patterns
8-
.pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression
9-
106
ast_lowering_argument = argument
117
128
ast_lowering_assoc_ty_binding_in_dyn =

compiler/rustc_ast_lowering/src/errors.rs

-9
Original file line numberDiff line numberDiff line change
@@ -363,15 +363,6 @@ pub struct NeverPatternWithGuard {
363363
pub span: Span,
364364
}
365365

366-
#[derive(Diagnostic)]
367-
#[diag(ast_lowering_arbitrary_expression_in_pattern)]
368-
pub struct ArbitraryExpressionInPattern {
369-
#[primary_span]
370-
pub span: Span,
371-
#[note(ast_lowering_pattern_from_macro_note)]
372-
pub pattern_from_macro_note: bool,
373-
}
374-
375366
#[derive(Diagnostic)]
376367
#[diag(ast_lowering_inclusive_range_with_no_end)]
377368
pub struct InclusiveRangeWithNoEnd {

compiler/rustc_ast_lowering/src/pat.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use super::errors::{
2-
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
3-
};
1+
use super::errors::{ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding};
42
use super::ResolverAstLoweringExt;
53
use super::{ImplTraitContext, LoweringContext, ParamMode};
64
use crate::ImplTraitPosition;
@@ -338,14 +336,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
338336
| ExprKind::Dummy => {}
339337
ExprKind::Path(..) if allow_paths => {}
340338
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
341-
_ => {
342-
let pattern_from_macro = expr.is_approximately_pattern();
343-
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
344-
span: expr.span,
345-
pattern_from_macro_note: pattern_from_macro,
346-
});
347-
return self.arena.alloc(self.expr_err(expr.span, guar));
348-
}
339+
kind => panic!("unexpected expr kind {kind:?}"),
349340
}
350341
self.lower_expr(expr)
351342
}

compiler/rustc_parse/src/parser/expr.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -2197,15 +2197,26 @@ impl<'a> Parser<'a> {
21972197
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
21982198
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
21992199
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
2200-
if let token::Interpolated(nt) = &self.token.kind {
2200+
let whole = if let token::Interpolated(nt) = &self.token.kind {
22012201
match &**nt {
2202-
token::NtExpr(e) | token::NtLiteral(e) => {
2203-
let e = e.clone();
2204-
self.bump();
2205-
return Ok(e);
2206-
}
2207-
_ => {}
2208-
};
2202+
token::NtLiteral(e) => Some(e.clone()),
2203+
token::NtExpr(e) => match &e.kind {
2204+
ExprKind::Lit(_) => Some(e.clone()),
2205+
ExprKind::Unary(UnOp::Neg, inner)
2206+
if matches!(&inner.kind, ast::ExprKind::Lit(_)) =>
2207+
{
2208+
Some(e.clone())
2209+
}
2210+
_ => None,
2211+
},
2212+
_ => None,
2213+
}
2214+
} else {
2215+
None
2216+
};
2217+
if let Some(e) = whole {
2218+
self.bump();
2219+
return Ok(e);
22092220
}
22102221

22112222
let lo = self.token.span;

tests/ui/issues/issue-43250.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ fn main() {
44
macro_rules! m {
55
($a:expr) => {
66
let $a = 0;
7+
//~^ ERROR expected pattern, found expression `y`
8+
//~| ERROR expected pattern, found expression `C`
79
}
810
}
911
m!(y);
10-
//~^ ERROR arbitrary expressions aren't allowed in patterns
1112
m!(C);
12-
//~^ ERROR arbitrary expressions aren't allowed in patterns
1313
}

tests/ui/issues/issue-43250.stderr

+14-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
1-
error: arbitrary expressions aren't allowed in patterns
2-
--> $DIR/issue-43250.rs:9:8
1+
error: expected pattern, found expression `y`
2+
--> $DIR/issue-43250.rs:6:17
33
|
4+
LL | let $a = 0;
5+
| ^^ expected pattern
6+
...
47
LL | m!(y);
5-
| ^
8+
| ----- in this macro invocation
69
|
7-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
10+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
811

9-
error: arbitrary expressions aren't allowed in patterns
10-
--> $DIR/issue-43250.rs:11:8
12+
error: expected pattern, found expression `C`
13+
--> $DIR/issue-43250.rs:6:17
1114
|
15+
LL | let $a = 0;
16+
| ^^ expected pattern
17+
...
1218
LL | m!(C);
13-
| ^
19+
| ----- in this macro invocation
1420
|
15-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
21+
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
1622

1723
error: aborting due to 2 previous errors
1824

Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
macro_rules! foo {
22
($p:expr) => {
3-
if let $p = Some(42) {
3+
if let $p = Some(42) { //~ ERROR expected pattern, found expression `Some(3)`
44
return;
55
}
66
};
77
}
88

99
fn main() {
10-
foo!(Some(3)); //~ ERROR arbitrary expressions aren't allowed in patterns
10+
foo!(Some(3));
1111
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
error: arbitrary expressions aren't allowed in patterns
2-
--> $DIR/expr-in-pat-issue-99380.rs:10:10
1+
error: expected pattern, found expression `Some(3)`
2+
--> $DIR/expr-in-pat-issue-99380.rs:3:16
33
|
4+
LL | if let $p = Some(42) {
5+
| ^^ expected pattern
6+
...
47
LL | foo!(Some(3));
5-
| ^^^^^^^
8+
| ------------- in this macro invocation
69
|
7-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
10+
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
811

912
error: aborting due to 1 previous error
1013

tests/ui/macros/trace_faulty_macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ fn use_bang_macro_as_attr() {}
4343
fn use_derive_macro_as_attr() {}
4444

4545
macro_rules! test {
46-
(let $p:pat = $e:expr) => {test!(($p,$e))};
46+
(let $p:pat = $e:expr) => {test!(($p,$e))}; //~ ERROR expected pattern, found expression `1+1`
4747
// this should be expr
4848
// vvv
49-
(($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1+1`
49+
(($p:pat, $e:pat)) => {let $p = $e;};
5050
}
5151

5252
fn foo() {

tests/ui/macros/trace_faulty_macros.stderr

+5-10
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,18 @@ LL | #[derive(Debug)]
6969
LL | fn use_derive_macro_as_attr() {}
7070
| -------------------------------- not a `struct`, `enum` or `union`
7171

72-
error: expected expression, found pattern `1+1`
73-
--> $DIR/trace_faulty_macros.rs:49:37
72+
error: expected pattern, found expression `1+1`
73+
--> $DIR/trace_faulty_macros.rs:46:42
7474
|
7575
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
76-
| -- this is interpreted as expression, but it is expected to be pattern
76+
| ^^ expected pattern
7777
...
7878
LL | (($p:pat, $e:pat)) => {let $p = $e;};
79-
| ^^ expected expression
79+
| ------ while parsing argument for this `pat` macro fragment
8080
...
8181
LL | test!(let x = 1+1);
82-
| ------------------
83-
| | |
84-
| | this is expected to be expression
85-
| in this macro invocation
82+
| ------------------ in this macro invocation
8683
|
87-
= note: when forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type, not the underlying tokens
8884
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
8985

9086
note: trace_macro
@@ -107,7 +103,6 @@ LL | test!(let x = 1+1);
107103
= note: expanding `test! { let x = 1+1 }`
108104
= note: to `test! ((x, 1+1))`
109105
= note: expanding `test! { (x, 1+1) }`
110-
= note: to `let x = 1+1;`
111106

112107
error: aborting due to 5 previous errors
113108

tests/ui/macros/vec-macro-in-pattern.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
fn main() {
66
match Some(vec![42]) {
7-
Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns
7+
Some(vec![43]) => {} //~ ERROR expected pattern, found expression
88
_ => {}
99
}
1010
}
+6-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
error: arbitrary expressions aren't allowed in patterns
1+
error: expected pattern, found expression `< [_] > :: into_vec(#[rustc_box] $crate :: boxed :: Box :: new([43]))`
22
--> $DIR/vec-macro-in-pattern.rs:7:14
33
|
44
LL | Some(vec![43]) => {}
55
| ^^^^^^^^
6+
| |
7+
| expected pattern
8+
| in this macro invocation
9+
| this macro call doesn't expand to a pattern
610
|
7-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
8-
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
= note: this error originates in the macro `$crate::__rust_force_expr` which comes from the expansion of the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
912

1013
error: aborting due to 1 previous error
1114

tests/ui/match/expr_before_ident_pat.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ macro_rules! funny {
22
($a:expr, $b:ident) => {
33
match [1, 2] {
44
[$a, $b] => {}
5+
//~^ ERROR expected pattern, found expression `a`
56
}
67
};
78
}
89

910
fn main() {
1011
funny!(a, a);
11-
//~^ ERROR cannot find value `a` in this scope
12-
//~| ERROR arbitrary expressions aren't allowed in patterns
1312
}
+8-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
1-
error[E0425]: cannot find value `a` in this scope
2-
--> $DIR/expr_before_ident_pat.rs:10:12
1+
error: expected pattern, found expression `a`
2+
--> $DIR/expr_before_ident_pat.rs:4:14
33
|
4+
LL | [$a, $b] => {}
5+
| ^^ expected pattern
6+
...
47
LL | funny!(a, a);
5-
| ^ not found in this scope
6-
7-
error: arbitrary expressions aren't allowed in patterns
8-
--> $DIR/expr_before_ident_pat.rs:10:12
9-
|
10-
LL | funny!(a, a);
11-
| ^
8+
| ------------ in this macro invocation
129
|
13-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
10+
= note: this error originates in the macro `funny` (in Nightly builds, run with -Z macro-backtrace for more info)
1411

15-
error: aborting due to 2 previous errors
12+
error: aborting due to 1 previous error
1613

17-
For more information about this error, try `rustc --explain E0425`.

tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,20 @@
44
macro_rules! mac1 {
55
($eval:expr) => {
66
let mut $eval = ();
7-
//~^ ERROR `mut` must be followed by a named binding
7+
//~^ ERROR expected identifier, found expression `does_not_exist!()`
88
};
99
}
1010

1111
macro_rules! mac2 {
1212
($eval:pat) => {
1313
let mut $eval = ();
14-
//~^ ERROR `mut` must be followed by a named binding
15-
//~| ERROR expected identifier, found `does_not_exist!()`
14+
//~^ ERROR expected identifier, found `does_not_exist!()`
15+
//~| ERROR `mut` must be followed by a named binding
1616
};
1717
}
1818

1919
fn foo() {
2020
mac1! { does_not_exist!() }
21-
//~^ ERROR cannot find macro `does_not_exist` in this scope
2221
mac2! { does_not_exist!() }
2322
//~^ ERROR cannot find macro `does_not_exist` in this scope
2423
}

tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr

+5-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
error: `mut` must be followed by a named binding
2-
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:13
1+
error: expected identifier, found expression `does_not_exist!()`
2+
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:17
33
|
44
LL | let mut $eval = ();
5-
| ^^^^ help: remove the `mut` prefix
5+
| ^^^^^ expected identifier
66
...
77
LL | mac1! { does_not_exist!() }
88
| --------------------------- in this macro invocation
99
|
10-
= note: `mut` may be followed by `variable` and `variable @ pattern`
1110
= note: this error originates in the macro `mac1` (in Nightly builds, run with -Z macro-backtrace for more info)
1211

1312
error: expected identifier, found `does_not_exist!()`
@@ -34,16 +33,10 @@ LL | mac2! { does_not_exist!() }
3433
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
3534

3635
error: cannot find macro `does_not_exist` in this scope
37-
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13
36+
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:21:13
3837
|
3938
LL | mac2! { does_not_exist!() }
4039
| ^^^^^^^^^^^^^^
4140

42-
error: cannot find macro `does_not_exist` in this scope
43-
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13
44-
|
45-
LL | mac1! { does_not_exist!() }
46-
| ^^^^^^^^^^^^^^
47-
48-
error: aborting due to 5 previous errors
41+
error: aborting due to 4 previous errors
4942

tests/ui/pattern/issue-92074-macro-ice.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,19 @@ fn get_usize() -> usize {
77
}
88

99
macro_rules! force_expr {
10-
($e:expr) => { $e }
10+
($e:expr) => { $e } //~ ERROR expected pattern, found expression `Vec :: new()`
1111
}
1212

1313
macro_rules! force_pat {
14-
($a:expr, $b:expr) => { $a..=$b }
14+
($a:expr, $b:expr) => { $a..=$b } //~ ERROR expected pattern, found expression `get_usize()`
1515
}
1616

1717
macro_rules! make_vec {
18-
() => { force_expr!(Vec::new()) } //~ ERROR arbitrary expressions aren't allowed
18+
() => { force_expr!(Vec::new()) }
1919
}
2020

2121
macro_rules! make_pat {
2222
() => { force_pat!(get_usize(), get_usize()) }
23-
//~^ ERROR arbitrary expressions aren't allowed
24-
//~| ERROR arbitrary expressions aren't allowed
2523
}
2624

2725
#[allow(unreachable_code)]

0 commit comments

Comments
 (0)