Skip to content

Commit 79097c2

Browse files
committed
Auto merge of rust-lang#129289 - nnethercote:fix-parse_maybe_literal_minus-1, r=<try>
Restrict `parse_maybe_literal_minus` `parse_literal_maybe_minus` currently accepts to many kinds of `NtExpr`. This PR starts the process of restricting it. r? `@petrochenkov`
2 parents fdf61d4 + 21efb72 commit 79097c2

11 files changed

+160
-67
lines changed

compiler/rustc_parse/src/parser/expr.rs

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

22002213
let lo = self.token.span;
Lines changed: 2 additions & 2 deletions
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
}
Lines changed: 7 additions & 4 deletions
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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Tests some cases relating to `parse_literal_maybe_minus`, which used to
2+
// accept more interpolated expressions than it should have.
3+
4+
const A: u32 = 0;
5+
const B: u32 = 1;
6+
7+
macro_rules! identity {
8+
($val:expr) => { $val }
9+
}
10+
11+
macro_rules! range1 {
12+
($min:expr) => {
13+
$min..
14+
}
15+
}
16+
17+
macro_rules! range2 {
18+
($min:expr, $max:expr) => {
19+
$min ..= $max
20+
}
21+
}
22+
23+
macro_rules! range3 {
24+
($max:expr) => {
25+
.. $max
26+
}
27+
}
28+
29+
macro_rules! m {
30+
($a:expr, $b:ident, $identity_mac_call:expr) => {
31+
fn _f() {
32+
match [1, 2] {
33+
[$a, $b] => {} // FIXME: doesn't compile, probably should
34+
_ => {}
35+
}
36+
37+
match (1, 2) {
38+
($a, $b) => {} // FIXME: doesn't compile, probably should
39+
_ => {}
40+
}
41+
42+
match 3 {
43+
$identity_mac_call => {}
44+
0..$identity_mac_call => {}
45+
_ => {}
46+
}
47+
}
48+
};
49+
}
50+
51+
m!(A, B, identity!(10));
52+
//~^ ERROR arbitrary expressions aren't allowed in patterns
53+
//~| ERROR arbitrary expressions aren't allowed in patterns
54+
55+
fn main() {
56+
match 3 {
57+
identity!(A) => {} // FIXME: doesn't compile, probably should
58+
//~^ ERROR arbitrary expressions aren't allowed in patterns
59+
range1!(A) => {}
60+
range2!(A, B) => {}
61+
range3!(B) => {}
62+
_ => {}
63+
}
64+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error: arbitrary expressions aren't allowed in patterns
2+
--> $DIR/parse-literal-maybe-minus.rs:57:19
3+
|
4+
LL | identity!(A) => {} // FIXME: doesn't compile, probably should
5+
| ^
6+
|
7+
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
8+
9+
error: arbitrary expressions aren't allowed in patterns
10+
--> $DIR/parse-literal-maybe-minus.rs:51:4
11+
|
12+
LL | m!(A, B, identity!(10));
13+
| ^
14+
|
15+
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
16+
17+
error: arbitrary expressions aren't allowed in patterns
18+
--> $DIR/parse-literal-maybe-minus.rs:51:4
19+
|
20+
LL | m!(A, B, identity!(10));
21+
| ^
22+
|
23+
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
24+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
25+
26+
error: aborting due to 3 previous errors
27+

tests/ui/macros/trace_faulty_macros.rs

Lines changed: 2 additions & 2 deletions
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

Lines changed: 5 additions & 10 deletions
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

Lines changed: 3 additions & 5 deletions
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)]
Lines changed: 14 additions & 22 deletions
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

Lines changed: 2 additions & 2 deletions
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() {}
Lines changed: 13 additions & 12 deletions
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)