Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restrict parse_maybe_literal_minus #129289

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2177,7 +2177,7 @@ impl<'a> Parser<'a> {
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
if let token::Interpolated(nt) = &self.token.kind {
let expr = if let token::Interpolated(nt) = &self.token.kind {
match &**nt {
// FIXME(nnethercote) The `NtExpr` case should only match if
// `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing
Expand All @@ -2189,13 +2189,26 @@ impl<'a> Parser<'a> {
// `ExprKind::Path` must be accepted when parsing range
// patterns. That requires some care. So for now, we continue
// being less strict here than we should be.
token::NtExpr(e) | token::NtLiteral(e) => {
let e = e.clone();
self.bump();
return Ok(e);
}
_ => {}
};
token::NtLiteral(e) => Some(e.clone()),
token::NtExpr(e) => match &e.kind {
ExprKind::Lit(_) | ExprKind::Path(None, _) | ExprKind::MacCall(_) => {
Some(e.clone())
}
ExprKind::Unary(UnOp::Neg, inner)
if matches!(&inner.kind, ast::ExprKind::Lit(_)) =>
{
Some(e.clone())
}
_ => None,
},
_ => None,
}
} else {
None
};
if let Some(e) = expr {
self.bump();
return Ok(e);
}

let lo = self.token.span;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/lowering/expr-in-pat-issue-99380.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
macro_rules! foo {
($p:expr) => {
if let $p = Some(42) {
if let $p = Some(42) { //~ ERROR expected pattern, found expression `Some(3)`
return;
}
};
}

fn main() {
foo!(Some(3)); //~ ERROR arbitrary expressions aren't allowed in patterns
foo!(Some(3));
}
11 changes: 7 additions & 4 deletions tests/ui/lowering/expr-in-pat-issue-99380.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/expr-in-pat-issue-99380.rs:10:10
error: expected pattern, found expression `Some(3)`
--> $DIR/expr-in-pat-issue-99380.rs:3:16
|
LL | if let $p = Some(42) {
| ^^ expected pattern
...
LL | foo!(Some(3));
| ^^^^^^^
| ------------- 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 `foo` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

64 changes: 64 additions & 0 deletions tests/ui/macros/parse-literal-maybe-minus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Tests some cases relating to `parse_literal_maybe_minus`, which used to
// accept more interpolated expressions than it should have.

const A: u32 = 0;
const B: u32 = 1;

macro_rules! identity {
($val:expr) => { $val }
}

macro_rules! range1 {
($min:expr) => {
$min..
}
}

macro_rules! range2 {
($min:expr, $max:expr) => {
$min ..= $max
}
}

macro_rules! range3 {
($max:expr) => {
.. $max
}
}

macro_rules! m {
($a:expr, $b:ident, $identity_mac_call:expr) => {
fn _f() {
match [1, 2] {
[$a, $b] => {} // FIXME: doesn't compile, probably should
_ => {}
}

match (1, 2) {
($a, $b) => {} // FIXME: doesn't compile, probably should
_ => {}
}

match 3 {
$identity_mac_call => {}
0..$identity_mac_call => {}
_ => {}
}
}
};
}

m!(A, B, identity!(10));
//~^ ERROR arbitrary expressions aren't allowed in patterns
//~| ERROR arbitrary expressions aren't allowed in patterns

fn main() {
match 3 {
identity!(A) => {} // FIXME: doesn't compile, probably should
//~^ ERROR arbitrary expressions aren't allowed in patterns
range1!(A) => {}
range2!(A, B) => {}
range3!(B) => {}
_ => {}
}
}
27 changes: 27 additions & 0 deletions tests/ui/macros/parse-literal-maybe-minus.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/parse-literal-maybe-minus.rs:57:19
|
LL | identity!(A) => {} // FIXME: doesn't compile, probably should
| ^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression

error: arbitrary expressions aren't allowed in patterns
--> $DIR/parse-literal-maybe-minus.rs:51:4
|
LL | m!(A, B, identity!(10));
| ^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression

error: arbitrary expressions aren't allowed in patterns
--> $DIR/parse-literal-maybe-minus.rs:51:4
|
LL | m!(A, B, identity!(10));
| ^
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 3 previous errors

4 changes: 2 additions & 2 deletions tests/ui/macros/trace_faulty_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ fn use_bang_macro_as_attr() {}
fn use_derive_macro_as_attr() {}

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

fn foo() {
Expand Down
15 changes: 5 additions & 10 deletions tests/ui/macros/trace_faulty_macros.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,18 @@ LL | #[derive(Debug)]
LL | fn use_derive_macro_as_attr() {}
| -------------------------------- not a `struct`, `enum` or `union`

error: expected expression, found pattern `1+1`
--> $DIR/trace_faulty_macros.rs:49:37
error: expected pattern, found expression `1+1`
--> $DIR/trace_faulty_macros.rs:46:42
|
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
| -- this is interpreted as expression, but it is expected to be pattern
| ^^ expected pattern
...
LL | (($p:pat, $e:pat)) => {let $p = $e;};
| ^^ expected expression
| ------ while parsing argument for this `pat` macro fragment
...
LL | test!(let x = 1+1);
| ------------------
| | |
| | this is expected to be expression
| in this macro invocation
| ------------------ in this macro invocation
|
= 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
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)

note: trace_macro
Expand All @@ -107,7 +103,6 @@ LL | test!(let x = 1+1);
= note: expanding `test! { let x = 1+1 }`
= note: to `test! ((x, 1+1))`
= note: expanding `test! { (x, 1+1) }`
= note: to `let x = 1+1;`

error: aborting due to 5 previous errors

Expand Down
8 changes: 3 additions & 5 deletions tests/ui/pattern/issue-92074-macro-ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,19 @@ fn get_usize() -> usize {
}

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

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

macro_rules! make_vec {
() => { force_expr!(Vec::new()) } //~ ERROR arbitrary expressions aren't allowed
() => { force_expr!(Vec::new()) }
}

macro_rules! make_pat {
() => { force_pat!(get_usize(), get_usize()) }
//~^ ERROR arbitrary expressions aren't allowed
//~| ERROR arbitrary expressions aren't allowed
}

#[allow(unreachable_code)]
Expand Down
36 changes: 14 additions & 22 deletions tests/ui/pattern/issue-92074-macro-ice.stderr
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/issue-92074-macro-ice.rs:18:25
error: expected pattern, found expression `Vec :: new()`
--> $DIR/issue-92074-macro-ice.rs:10:20
|
LL | ($e:expr) => { $e }
| ^^ expected pattern
...
LL | () => { force_expr!(Vec::new()) }
| ^^^^^^^^^^
| ----------------------- this macro call doesn't expand to a pattern
...
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)
= 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)

error: arbitrary expressions aren't allowed in patterns
--> $DIR/issue-92074-macro-ice.rs:22:24
error: expected pattern, found expression `get_usize()`
--> $DIR/issue-92074-macro-ice.rs:14:29
|
LL | () => { force_pat!(get_usize(), get_usize()) }
| ^^^^^^^^^^^
LL | ($a:expr, $b:expr) => { $a..=$b }
| ^^ expected pattern
...
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
--> $DIR/issue-92074-macro-ice.rs:22:37
|
LL | () => { force_pat!(get_usize(), get_usize()) }
| ^^^^^^^^^^^
| ------------------------------------ this macro call doesn't expand to a pattern
...
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)
= 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)

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

4 changes: 2 additions & 2 deletions tests/ui/pattern/patkind-litrange-no-expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ macro_rules! enum_number {
fn foo(value: i32) -> Option<$name> {
match value {
$( $value => Some($name::$variant), )* // PatKind::Lit
//~^ ERROR expected pattern, found expression `1 + 1`
$( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
_ => None
}
Expand All @@ -17,8 +18,7 @@ macro_rules! enum_number {
enum_number!(Change {
Pos = 1,
Neg = -1,
Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
//~| ERROR arbitrary expressions aren't allowed in patterns
Arith = 1 + 1,
});

fn main() {}
25 changes: 13 additions & 12 deletions tests/ui/pattern/patkind-litrange-no-expr.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/patkind-litrange-no-expr.rs:20:13
error: expected pattern, found expression `1 + 1`
--> $DIR/patkind-litrange-no-expr.rs:9:20
|
LL | Arith = 1 + 1,
| ^^^^^

error: arbitrary expressions aren't allowed in patterns
--> $DIR/patkind-litrange-no-expr.rs:20:13
|
LL | Arith = 1 + 1,
| ^^^^^
LL | $( $value => Some($name::$variant), )* // PatKind::Lit
| ^^^^^^ expected pattern
...
LL | / enum_number!(Change {
LL | | Pos = 1,
LL | | Neg = -1,
LL | | Arith = 1 + 1,
LL | | });
| |__- in this macro invocation
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
= note: this error originates in the macro `enum_number` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

Loading