Skip to content

Commit d33b356

Browse files
committed
parser: Do not call bump recursively
Token normalization is merged directly into `bump`. Special "unknown macro variable" diagnostic for unexpected `$`s is removed as preventing legal code from compiling.
1 parent 0176a9e commit d33b356

File tree

7 files changed

+38
-52
lines changed

7 files changed

+38
-52
lines changed

src/librustc_expand/mbe/macro_parser.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,6 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
856856
if name == sym::tt {
857857
return token::NtTT(p.parse_token_tree());
858858
}
859-
// check at the beginning and the parser checks after each bump
860-
p.process_potential_macro_variable();
861859
match parse_nt_inner(p, sp, name) {
862860
Ok(nt) => nt,
863861
Err(mut err) => {

src/librustc_expand/mbe/macro_rules.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,6 @@ fn generic_extension<'cx>(
267267
cx.current_expansion.module.mod_path.last().map(|id| id.to_string());
268268
p.last_type_ascription = cx.current_expansion.prior_type_ascription;
269269

270-
p.process_potential_macro_variable();
271270
// Let the context choose how to interpret the result.
272271
// Weird, but useful for X-macros.
273272
return Box::new(ParserAnyMacro {

src/librustc_parse/parser/mod.rs

Lines changed: 32 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,8 @@ impl<'a> Parser<'a> {
404404
subparser_name,
405405
};
406406

407-
parser.token = parser.next_tok();
407+
// Make parser point to the first token.
408+
parser.bump();
408409

409410
if let Some(directory) = directory {
410411
parser.directory = directory;
@@ -418,7 +419,6 @@ impl<'a> Parser<'a> {
418419
}
419420
}
420421

421-
parser.process_potential_macro_variable();
422422
parser
423423
}
424424

@@ -430,15 +430,15 @@ impl<'a> Parser<'a> {
430430
self.unnormalized_prev_token.as_ref().unwrap_or(&self.prev_token)
431431
}
432432

433-
fn next_tok(&mut self) -> Token {
433+
fn next_tok(&mut self, fallback_span: Span) -> Token {
434434
let mut next = if self.desugar_doc_comments {
435435
self.token_cursor.next_desugared()
436436
} else {
437437
self.token_cursor.next()
438438
};
439439
if next.span.is_dummy() {
440440
// Tweak the location for better diagnostics, but keep syntactic context intact.
441-
next.span = self.unnormalized_token().span.with_ctxt(next.span.ctxt());
441+
next.span = fallback_span.with_ctxt(next.span.ctxt());
442442
}
443443
next
444444
}
@@ -896,6 +896,24 @@ impl<'a> Parser<'a> {
896896
self.parse_delim_comma_seq(token::Paren, f)
897897
}
898898

899+
// Interpolated identifier (`$i: ident`) and lifetime (`$l: lifetime`)
900+
// tokens are replaced with usual identifier and lifetime tokens,
901+
// so the former are never encountered during normal parsing.
902+
fn normalize_token(token: &Token) -> Option<Token> {
903+
match &token.kind {
904+
token::Interpolated(nt) => match **nt {
905+
token::NtIdent(ident, is_raw) => {
906+
Some(Token::new(token::Ident(ident.name, is_raw), ident.span))
907+
}
908+
token::NtLifetime(ident) => {
909+
Some(Token::new(token::Lifetime(ident.name), ident.span))
910+
}
911+
_ => None,
912+
},
913+
_ => None,
914+
}
915+
}
916+
899917
/// Advance the parser by one token.
900918
pub fn bump(&mut self) {
901919
if self.prev_token.kind == TokenKind::Eof {
@@ -905,16 +923,17 @@ impl<'a> Parser<'a> {
905923
}
906924

907925
// Update the current and previous tokens.
908-
let next_token = self.next_tok();
909-
self.prev_token = mem::replace(&mut self.token, next_token);
926+
self.prev_token = self.token.take();
910927
self.unnormalized_prev_token = self.unnormalized_token.take();
928+
self.token = self.next_tok(self.unnormalized_prev_token().span);
929+
if let Some(normalized_token) = Self::normalize_token(&self.token) {
930+
self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token));
931+
}
911932

912933
// Update fields derived from the previous token.
913934
self.prev_span = self.unnormalized_prev_token().span;
914935

915936
self.expected_tokens.clear();
916-
// Check after each token.
917-
self.process_potential_macro_variable();
918937
}
919938

920939
/// Advances the parser using provided token as a next one. Use this when
@@ -924,9 +943,12 @@ impl<'a> Parser<'a> {
924943
/// Correct token kinds and spans need to be calculated instead.
925944
fn bump_with(&mut self, next: TokenKind, span: Span) {
926945
// Update the current and previous tokens.
927-
let next_token = Token::new(next, span);
928-
self.prev_token = mem::replace(&mut self.token, next_token);
946+
self.prev_token = self.token.take();
929947
self.unnormalized_prev_token = self.unnormalized_token.take();
948+
self.token = Token::new(next, span);
949+
if let Some(normalized_token) = Self::normalize_token(&self.token) {
950+
self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token));
951+
}
930952

931953
// Update fields derived from the previous token.
932954
self.prev_span = self.unnormalized_prev_token().span.with_hi(span.lo());
@@ -1066,39 +1088,6 @@ impl<'a> Parser<'a> {
10661088
}
10671089
}
10681090

1069-
pub fn process_potential_macro_variable(&mut self) {
1070-
let normalized_token = match self.token.kind {
1071-
token::Dollar
1072-
if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) =>
1073-
{
1074-
self.bump();
1075-
let name = match self.token.kind {
1076-
token::Ident(name, _) => name,
1077-
_ => unreachable!(),
1078-
};
1079-
let span = self.prev_span.to(self.token.span);
1080-
self.struct_span_err(span, &format!("unknown macro variable `{}`", name))
1081-
.span_label(span, "unknown macro variable")
1082-
.emit();
1083-
self.bump();
1084-
return;
1085-
}
1086-
token::Interpolated(ref nt) => {
1087-
// Interpolated identifier and lifetime tokens are replaced with usual identifier
1088-
// and lifetime tokens, so the former are never encountered during normal parsing.
1089-
match **nt {
1090-
token::NtIdent(ident, is_raw) => {
1091-
Token::new(token::Ident(ident.name, is_raw), ident.span)
1092-
}
1093-
token::NtLifetime(ident) => Token::new(token::Lifetime(ident.name), ident.span),
1094-
_ => return,
1095-
}
1096-
}
1097-
_ => return,
1098-
};
1099-
self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token));
1100-
}
1101-
11021091
/// Parses a single token tree from the input.
11031092
pub fn parse_token_tree(&mut self) -> TokenTree {
11041093
match self.token.kind {

src/test/ui/issues/issue-6596-1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
macro_rules! e {
22
($inp:ident) => (
33
$nonexistent
4-
//~^ ERROR unknown macro variable `nonexistent`
4+
//~^ ERROR expected expression, found `$`
55
);
66
}
77

src/test/ui/issues/issue-6596-1.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: unknown macro variable `nonexistent`
1+
error: expected expression, found `$`
22
--> $DIR/issue-6596-1.rs:3:9
33
|
44
LL | $nonexistent
5-
| ^^^^^^^^^^^^ unknown macro variable
5+
| ^^^^^^^^^^^^ expected expression
66
...
77
LL | e!(foo);
88
| -------- in this macro invocation

src/test/ui/issues/issue-6596-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
macro_rules! g {
44
($inp:ident) => (
55
{ $inp $nonexistent }
6-
//~^ ERROR unknown macro variable `nonexistent`
6+
//~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$`
77
);
88
}
99

src/test/ui/issues/issue-6596-2.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: unknown macro variable `nonexistent`
1+
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$`
22
--> $DIR/issue-6596-2.rs:5:16
33
|
44
LL | { $inp $nonexistent }
5-
| ^^^^^^^^^^^^ unknown macro variable
5+
| ^^^^^^^^^^^^ expected one of 8 possible tokens
66
...
77
LL | g!(foo);
88
| -------- in this macro invocation

0 commit comments

Comments
 (0)