diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index e5a1c6c789928..b2f7c8f5183a2 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -54,18 +54,24 @@ pub(super) fn parse( // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming // additional trees if need be. - let mut trees = input.trees(); + let mut trees = input.trees().peekable(); while let Some(tree) = trees.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). let tree = parse_tree(tree, &mut trees, parsing_patterns, sess, node_id, features, edition); match tree { TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { - let span = match trees.next() { + // Not consuming the next token immediately, as it may not be a colon + let span = match trees.peek() { Some(&tokenstream::TokenTree::Token( Token { kind: token::Colon, span: colon_span }, _, )) => { + // Consume the colon first + trees.next(); + + // It's ok to consume the next tree no matter how, + // since if it's not a token then it will be an invalid declaration. match trees.next() { Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { Some((fragment, _)) => { @@ -125,12 +131,13 @@ pub(super) fn parse( } _ => token.span, }, - Some(tree) => tree.span(), - None => colon_span, + // Invalid, return a nice source location + _ => colon_span.with_lo(start_sp.lo()), } } - Some(tree) => tree.span(), - None => start_sp, + // Whether it's none or some other tree, it doesn't belong to + // the current meta variable, returning the original span. + _ => start_sp, }; result.push(TokenTree::MetaVarDecl(span, ident, None)); diff --git a/tests/ui/macros/macro-match-nonterminal.stderr b/tests/ui/macros/macro-match-nonterminal.stderr index 831579c4fefd5..f221f92c3cda6 100644 --- a/tests/ui/macros/macro-match-nonterminal.stderr +++ b/tests/ui/macros/macro-match-nonterminal.stderr @@ -1,14 +1,14 @@ error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:8 + --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { - | ^ + | ^^ error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:8 + --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { - | ^ + | ^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107 @@ -27,10 +27,10 @@ error: aborting due to 3 previous errors Future incompatibility report: Future breakage diagnostic: error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:2:8 + --> $DIR/macro-match-nonterminal.rs:2:6 | LL | ($a, $b) => { - | ^ + | ^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #40107