Skip to content

Commit 21efb72

Browse files
committed
Restrict NtExpr cases allowed in parse_literal_maybe_minus.
The end goal is to only allow `ExprKind::Lit` and `ExprKind::Unary`/`Unop::Neg` interpolated expressions. We can't do that yet, because we still need to allow `ExprKind::Path` and `ExprKind::MacCall`. Some tests have their output changed, because some invalid code is now rejected during parsing instead of during HIR lowering. Each error location moves from a macro call site to a macro body, which I think is an improvement.
1 parent 1ee4f6f commit 21efb72

9 files changed

+69
-67
lines changed

compiler/rustc_parse/src/parser/expr.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -2177,7 +2177,7 @@ impl<'a> Parser<'a> {
21772177
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
21782178
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
21792179
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
2180-
if let token::Interpolated(nt) = &self.token.kind {
2180+
let expr = if let token::Interpolated(nt) = &self.token.kind {
21812181
match &**nt {
21822182
// FIXME(nnethercote) The `NtExpr` case should only match if
21832183
// `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing
@@ -2189,13 +2189,26 @@ impl<'a> Parser<'a> {
21892189
// `ExprKind::Path` must be accepted when parsing range
21902190
// patterns. That requires some care. So for now, we continue
21912191
// being less strict here than we should be.
2192-
token::NtExpr(e) | token::NtLiteral(e) => {
2193-
let e = e.clone();
2194-
self.bump();
2195-
return Ok(e);
2196-
}
2197-
_ => {}
2198-
};
2192+
token::NtLiteral(e) => Some(e.clone()),
2193+
token::NtExpr(e) => match &e.kind {
2194+
ExprKind::Lit(_) | ExprKind::Path(None, _) | ExprKind::MacCall(_) => {
2195+
Some(e.clone())
2196+
}
2197+
ExprKind::Unary(UnOp::Neg, inner)
2198+
if matches!(&inner.kind, ast::ExprKind::Lit(_)) =>
2199+
{
2200+
Some(e.clone())
2201+
}
2202+
_ => None,
2203+
},
2204+
_ => None,
2205+
}
2206+
} else {
2207+
None
2208+
};
2209+
if let Some(e) = expr {
2210+
self.bump();
2211+
return Ok(e);
21992212
}
22002213

22012214
let lo = self.token.span;
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/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)]
+14-22
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,30 @@
1-
error: arbitrary expressions aren't allowed in patterns
2-
--> $DIR/issue-92074-macro-ice.rs:18:25
1+
error: expected pattern, found expression `Vec :: new()`
2+
--> $DIR/issue-92074-macro-ice.rs:10:20
33
|
4+
LL | ($e:expr) => { $e }
5+
| ^^ expected pattern
6+
...
47
LL | () => { force_expr!(Vec::new()) }
5-
| ^^^^^^^^^^
8+
| ----------------------- this macro call doesn't expand to a pattern
69
...
710
LL | assert!(matches!(x, En::A(make_vec!())));
811
| ----------- in this macro invocation
912
|
10-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
11-
= note: this error originates in the macro `make_vec` (in Nightly builds, run with -Z macro-backtrace for more info)
13+
= note: this error originates in the macro `force_expr` which comes from the expansion of the macro `make_vec` (in Nightly builds, run with -Z macro-backtrace for more info)
1214

13-
error: arbitrary expressions aren't allowed in patterns
14-
--> $DIR/issue-92074-macro-ice.rs:22:24
15+
error: expected pattern, found expression `get_usize()`
16+
--> $DIR/issue-92074-macro-ice.rs:14:29
1517
|
16-
LL | () => { force_pat!(get_usize(), get_usize()) }
17-
| ^^^^^^^^^^^
18+
LL | ($a:expr, $b:expr) => { $a..=$b }
19+
| ^^ expected pattern
1820
...
19-
LL | assert!(matches!(5, make_pat!()));
20-
| ----------- in this macro invocation
21-
|
22-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
23-
= note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info)
24-
25-
error: arbitrary expressions aren't allowed in patterns
26-
--> $DIR/issue-92074-macro-ice.rs:22:37
27-
|
2821
LL | () => { force_pat!(get_usize(), get_usize()) }
29-
| ^^^^^^^^^^^
22+
| ------------------------------------ this macro call doesn't expand to a pattern
3023
...
3124
LL | assert!(matches!(5, make_pat!()));
3225
| ----------- in this macro invocation
3326
|
34-
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
35-
= note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info)
27+
= note: this error originates in the macro `force_pat` which comes from the expansion of the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info)
3628

37-
error: aborting due to 3 previous errors
29+
error: aborting due to 2 previous errors
3830

tests/ui/pattern/patkind-litrange-no-expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ macro_rules! enum_number {
77
fn foo(value: i32) -> Option<$name> {
88
match value {
99
$( $value => Some($name::$variant), )* // PatKind::Lit
10+
//~^ ERROR expected pattern, found expression `1 + 1`
1011
$( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
1112
_ => None
1213
}
@@ -17,8 +18,7 @@ macro_rules! enum_number {
1718
enum_number!(Change {
1819
Pos = 1,
1920
Neg = -1,
20-
Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
21-
//~| ERROR arbitrary expressions aren't allowed in patterns
21+
Arith = 1 + 1,
2222
});
2323

2424
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
error: arbitrary expressions aren't allowed in patterns
2-
--> $DIR/patkind-litrange-no-expr.rs:20:13
1+
error: expected pattern, found expression `1 + 1`
2+
--> $DIR/patkind-litrange-no-expr.rs:9:20
33
|
4-
LL | Arith = 1 + 1,
5-
| ^^^^^
6-
7-
error: arbitrary expressions aren't allowed in patterns
8-
--> $DIR/patkind-litrange-no-expr.rs:20:13
9-
|
10-
LL | Arith = 1 + 1,
11-
| ^^^^^
4+
LL | $( $value => Some($name::$variant), )* // PatKind::Lit
5+
| ^^^^^^ expected pattern
6+
...
7+
LL | / enum_number!(Change {
8+
LL | | Pos = 1,
9+
LL | | Neg = -1,
10+
LL | | Arith = 1 + 1,
11+
LL | | });
12+
| |__- in this macro invocation
1213
|
13-
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
14+
= note: this error originates in the macro `enum_number` (in Nightly builds, run with -Z macro-backtrace for more info)
1415

15-
error: aborting due to 2 previous errors
16+
error: aborting due to 1 previous error
1617

0 commit comments

Comments
 (0)