Rollup merge of #129154 - wafarm:fix-95463, r=estebank

Fix wrong source location for some incorrect macro definitions

Fixes #95463

Currently the code will consume the next token tree after `var` when trying to parse `$var:some_type` even when it's not a `:` (e.g. a `$` when input is `($foo $bar:tt) => {}`). Additionally it will return the wrong span when it's not a `:`.

This PR fixes these problems.
This commit is contained in:
Matthias Krüger 2024-08-16 19:58:59 +02:00 committed by GitHub
commit 5bceee4762
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 19 additions and 12 deletions

View File

@ -54,18 +54,24 @@ pub(super) fn parse(
// For each token tree in `input`, parse the token into a `self::TokenTree`, consuming // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming
// additional trees if need be. // additional trees if need be.
let mut trees = input.trees(); let mut trees = input.trees().peekable();
while let Some(tree) = trees.next() { while let Some(tree) = trees.next() {
// Given the parsed tree, if there is a metavar and we are expecting matchers, actually // 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`). // 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); let tree = parse_tree(tree, &mut trees, parsing_patterns, sess, node_id, features, edition);
match tree { match tree {
TokenTree::MetaVar(start_sp, ident) if parsing_patterns => { 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( Some(&tokenstream::TokenTree::Token(
Token { kind: token::Colon, span: colon_span }, 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() { match trees.next() {
Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() { Some(tokenstream::TokenTree::Token(token, _)) => match token.ident() {
Some((fragment, _)) => { Some((fragment, _)) => {
@ -125,12 +131,13 @@ pub(super) fn parse(
} }
_ => token.span, _ => token.span,
}, },
Some(tree) => tree.span(), // Invalid, return a nice source location
None => colon_span, _ => colon_span.with_lo(start_sp.lo()),
} }
} }
Some(tree) => tree.span(), // Whether it's none or some other tree, it doesn't belong to
None => start_sp, // the current meta variable, returning the original span.
_ => start_sp,
}; };
result.push(TokenTree::MetaVarDecl(span, ident, None)); result.push(TokenTree::MetaVarDecl(span, ident, None));

View File

@ -1,14 +1,14 @@
error: missing fragment specifier error: missing fragment specifier
--> $DIR/macro-match-nonterminal.rs:2:8 --> $DIR/macro-match-nonterminal.rs:2:6
| |
LL | ($a, $b) => { LL | ($a, $b) => {
| ^ | ^^
error: missing fragment specifier error: missing fragment specifier
--> $DIR/macro-match-nonterminal.rs:2:8 --> $DIR/macro-match-nonterminal.rs:2:6
| |
LL | ($a, $b) => { 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! = 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 <https://github.com/rust-lang/rust/issues/40107> = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
@ -27,10 +27,10 @@ error: aborting due to 3 previous errors
Future incompatibility report: Future breakage diagnostic: Future incompatibility report: Future breakage diagnostic:
error: missing fragment specifier error: missing fragment specifier
--> $DIR/macro-match-nonterminal.rs:2:8 --> $DIR/macro-match-nonterminal.rs:2:6
| |
LL | ($a, $b) => { 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! = 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 <https://github.com/rust-lang/rust/issues/40107> = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>