diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7fda9158b4bdf..7096d6799e2cd 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -143,6 +143,7 @@ macro_rules! maybe_whole_expr { $p.token.span, ExprKind::Block(block, None), ThinVec::new() )); } + // N.B: `NtIdent(ident)` is normalized to `Ident` in `fn bump`. _ => {}, }; } @@ -2756,12 +2757,7 @@ impl<'a> Parser<'a> { // can't continue an expression after an ident token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), token::Literal(..) | token::Pound => true, - token::Interpolated(ref nt) => match **nt { - token::NtIdent(..) | token::NtExpr(..) | - token::NtBlock(..) | token::NtPath(..) => true, - _ => false, - }, - _ => false + _ => t.is_whole_expr(), }; let cannot_continue_expr = self.look_ahead(1, token_cannot_continue_expr); if cannot_continue_expr { @@ -3728,6 +3724,7 @@ impl<'a> Parser<'a> { self.token.is_path_start() // e.g. `MY_CONST`; || self.token == token::Dot // e.g. `.5` for recovery; || self.token.can_begin_literal_or_bool() // e.g. `42`. + || self.token.is_whole_expr() } // Helper function to decide whether to parse as ident binding diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 472e4b474d627..73adb5c947c0b 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -476,6 +476,19 @@ impl Token { false } + /// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`? + /// That is, is this a pre-parsed expression dropped into the token stream + /// (which happens while parsing the result of macro expansion)? + crate fn is_whole_expr(&self) -> bool { + if let Interpolated(ref nt) = self.kind { + if let NtExpr(_) | NtLiteral(_) | NtPath(_) | NtIdent(..) | NtBlock(_) = **nt { + return true; + } + } + + false + } + /// Returns `true` if the token is either the `mut` or `const` keyword. crate fn is_mutability(&self) -> bool { self.is_keyword(kw::Mut) || diff --git a/src/test/ui/parser/issue-63115-range-pat-interpolated.rs b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs new file mode 100644 index 0000000000000..a7d10ca9320a6 --- /dev/null +++ b/src/test/ui/parser/issue-63115-range-pat-interpolated.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(exclusive_range_pattern)] + +#![allow(ellipsis_inclusive_range_patterns)] + +fn main() { + macro_rules! mac_expr { + ($e:expr) => { + if let 2...$e = 3 {} + if let 2..=$e = 3 {} + if let 2..$e = 3 {} + } + } + mac_expr!(4); +} diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs index c66652ff4fa01..260e108315973 100644 --- a/src/test/ui/parser/recover-range-pats.rs +++ b/src/test/ui/parser/recover-range-pats.rs @@ -121,3 +121,31 @@ fn inclusive2_to() { //~| ERROR `...` range patterns are deprecated //~| ERROR mismatched types } + +fn with_macro_expr_var() { + macro_rules! mac2 { + ($e1:expr, $e2:expr) => { + let $e1..$e2; + let $e1...$e2; + //~^ ERROR `...` range patterns are deprecated + let $e1..=$e2; + } + } + + mac2!(0, 1); + + macro_rules! mac { + ($e:expr) => { + let ..$e; //~ ERROR `..X` range patterns are not supported + let ...$e; //~ ERROR `...X` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + let ..=$e; //~ ERROR `..=X` range patterns are not supported + let $e..; //~ ERROR `X..` range patterns are not supported + let $e...; //~ ERROR `X...` range patterns are not supported + //~^ ERROR `...` range patterns are deprecated + let $e..=; //~ ERROR `X..=` range patterns are not supported + } + } + + mac!(0); +} diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr index c50d5e6eb6153..89ec059cb8234 100644 --- a/src/test/ui/parser/recover-range-pats.stderr +++ b/src/test/ui/parser/recover-range-pats.stderr @@ -214,6 +214,60 @@ error: `...X` range patterns are not supported LL | if let ....3 = 0 {} | ^^^^^ help: try using the minimum value for the type: `MIN...0.3` +error: `..X` range patterns are not supported + --> $DIR/recover-range-pats.rs:139:17 + | +LL | let ..$e; + | ^^ help: try using the minimum value for the type: `MIN..0` +... +LL | mac!(0); + | -------- in this macro invocation + +error: `...X` range patterns are not supported + --> $DIR/recover-range-pats.rs:140:17 + | +LL | let ...$e; + | ^^^ help: try using the minimum value for the type: `MIN...0` +... +LL | mac!(0); + | -------- in this macro invocation + +error: `..=X` range patterns are not supported + --> $DIR/recover-range-pats.rs:142:17 + | +LL | let ..=$e; + | ^^^ help: try using the minimum value for the type: `MIN..=0` +... +LL | mac!(0); + | -------- in this macro invocation + +error: `X..` range patterns are not supported + --> $DIR/recover-range-pats.rs:143:19 + | +LL | let $e..; + | ^^ help: try using the maximum value for the type: `0..MAX` +... +LL | mac!(0); + | -------- in this macro invocation + +error: `X...` range patterns are not supported + --> $DIR/recover-range-pats.rs:144:19 + | +LL | let $e...; + | ^^^ help: try using the maximum value for the type: `0...MAX` +... +LL | mac!(0); + | -------- in this macro invocation + +error: `X..=` range patterns are not supported + --> $DIR/recover-range-pats.rs:146:19 + | +LL | let $e..=; + | ^^^ help: try using the maximum value for the type: `0..=MAX` +... +LL | mac!(0); + | -------- in this macro invocation + error: `...` range patterns are deprecated --> $DIR/recover-range-pats.rs:41:13 | @@ -316,6 +370,33 @@ error: `...` range patterns are deprecated LL | if let ....3 = 0 {} | ^^^ help: use `..=` for an inclusive range +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:129:20 + | +LL | let $e1...$e2; + | ^^^ help: use `..=` for an inclusive range +... +LL | mac2!(0, 1); + | ------------ in this macro invocation + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:140:17 + | +LL | let ...$e; + | ^^^ help: use `..=` for an inclusive range +... +LL | mac!(0); + | -------- in this macro invocation + +error: `...` range patterns are deprecated + --> $DIR/recover-range-pats.rs:144:19 + | +LL | let $e...; + | ^^^ help: use `..=` for an inclusive range +... +LL | mac!(0); + | -------- in this macro invocation + error[E0029]: only char and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:19:12 | @@ -532,7 +613,7 @@ LL | if let ....3 = 0 {} = note: expected type `{integer}` found type `{float}` -error: aborting due to 76 previous errors +error: aborting due to 85 previous errors Some errors have detailed explanations: E0029, E0308. For more information about an error, try `rustc --explain E0029`.