diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e0917ba43e41c..ed7e386e340c2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -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> { - 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 @@ -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; diff --git a/tests/ui/lowering/expr-in-pat-issue-99380.rs b/tests/ui/lowering/expr-in-pat-issue-99380.rs index 1d4a047f717f7..f6d830cc1c9f5 100644 --- a/tests/ui/lowering/expr-in-pat-issue-99380.rs +++ b/tests/ui/lowering/expr-in-pat-issue-99380.rs @@ -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)); } diff --git a/tests/ui/lowering/expr-in-pat-issue-99380.stderr b/tests/ui/lowering/expr-in-pat-issue-99380.stderr index 29438c9b06360..fbe61bd08e4fb 100644 --- a/tests/ui/lowering/expr-in-pat-issue-99380.stderr +++ b/tests/ui/lowering/expr-in-pat-issue-99380.stderr @@ -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 diff --git a/tests/ui/macros/parse-literal-maybe-minus.rs b/tests/ui/macros/parse-literal-maybe-minus.rs new file mode 100644 index 0000000000000..7983a327d801e --- /dev/null +++ b/tests/ui/macros/parse-literal-maybe-minus.rs @@ -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) => {} + _ => {} + } +} diff --git a/tests/ui/macros/parse-literal-maybe-minus.stderr b/tests/ui/macros/parse-literal-maybe-minus.stderr new file mode 100644 index 0000000000000..45976f3818108 --- /dev/null +++ b/tests/ui/macros/parse-literal-maybe-minus.stderr @@ -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 + diff --git a/tests/ui/macros/trace_faulty_macros.rs b/tests/ui/macros/trace_faulty_macros.rs index 87036bb9c6f75..bef40e09e6f2f 100644 --- a/tests/ui/macros/trace_faulty_macros.rs +++ b/tests/ui/macros/trace_faulty_macros.rs @@ -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() { diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr index 66d7b76bb0726..56cd9fe231b11 100644 --- a/tests/ui/macros/trace_faulty_macros.stderr +++ b/tests/ui/macros/trace_faulty_macros.stderr @@ -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 @@ -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 diff --git a/tests/ui/pattern/issue-92074-macro-ice.rs b/tests/ui/pattern/issue-92074-macro-ice.rs index 039d3b314445d..98510696b5155 100644 --- a/tests/ui/pattern/issue-92074-macro-ice.rs +++ b/tests/ui/pattern/issue-92074-macro-ice.rs @@ -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)] diff --git a/tests/ui/pattern/issue-92074-macro-ice.stderr b/tests/ui/pattern/issue-92074-macro-ice.stderr index 025592116e511..606e7384b7cef 100644 --- a/tests/ui/pattern/issue-92074-macro-ice.stderr +++ b/tests/ui/pattern/issue-92074-macro-ice.stderr @@ -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 diff --git a/tests/ui/pattern/patkind-litrange-no-expr.rs b/tests/ui/pattern/patkind-litrange-no-expr.rs index 7ef541cb58528..43cf92a18b994 100644 --- a/tests/ui/pattern/patkind-litrange-no-expr.rs +++ b/tests/ui/pattern/patkind-litrange-no-expr.rs @@ -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 } @@ -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() {} diff --git a/tests/ui/pattern/patkind-litrange-no-expr.stderr b/tests/ui/pattern/patkind-litrange-no-expr.stderr index 45a2614894034..863ff2081ac23 100644 --- a/tests/ui/pattern/patkind-litrange-no-expr.stderr +++ b/tests/ui/pattern/patkind-litrange-no-expr.stderr @@ -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