Skip to content

Commit 8823634

Browse files
committed
Manually cleanup token stream when macro expansion aborts.
1 parent 5338f5f commit 8823634

File tree

3 files changed

+71
-15
lines changed

3 files changed

+71
-15
lines changed

compiler/rustc_parse/src/parser/attr_wrapper.rs

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -442,23 +442,38 @@ fn make_token_stream(
442442
}
443443
token_and_spacing = iter.next();
444444
}
445-
let mut final_buf = stack.pop().expect("Missing final buf!");
446-
if break_last_token {
447-
let last_token = final_buf.inner.pop().unwrap();
448-
if let AttrTokenTree::Token(last_token, spacing) = last_token {
449-
let unglued_first = last_token.kind.break_two_token_op().unwrap().0;
450-
451-
// An 'unglued' token is always two ASCII characters
452-
let mut first_span = last_token.span.shrink_to_lo();
453-
first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1));
454-
455-
final_buf
445+
while let Some(FrameData { open_delim_sp, mut inner }) = stack.pop() {
446+
// A former macro expansion could give us malformed tokens.
447+
// In that case, manually close all open delimitors so downstream users
448+
// don't ICE on them.
449+
if let Some((delim, open_sp)) = open_delim_sp {
450+
let dspan = DelimSpan::from_pair(open_sp, rustc_span::DUMMY_SP);
451+
let stream = AttrTokenStream::new(inner);
452+
let delimited = AttrTokenTree::Delimited(dspan, delim, stream);
453+
stack
454+
.last_mut()
455+
.unwrap_or_else(|| panic!("Bottom token frame is missing for recovered token"))
456456
.inner
457-
.push(AttrTokenTree::Token(Token::new(unglued_first, first_span), spacing));
457+
.push(delimited);
458458
} else {
459-
panic!("Unexpected last token {:?}", last_token)
459+
if break_last_token {
460+
let last_token = inner.pop().unwrap();
461+
if let AttrTokenTree::Token(last_token, spacing) = last_token {
462+
let unglued_first = last_token.kind.break_two_token_op().unwrap().0;
463+
464+
// An 'unglued' token is always two ASCII characters
465+
let mut first_span = last_token.span.shrink_to_lo();
466+
first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1));
467+
468+
inner
469+
.push(AttrTokenTree::Token(Token::new(unglued_first, first_span), spacing));
470+
} else {
471+
panic!("Unexpected last token {:?}", last_token)
472+
}
473+
}
474+
assert!(stack.is_empty(), "Stack should be empty: stack={:?}", stack);
475+
return AttrTokenStream::new(inner);
460476
}
461477
}
462-
assert!(stack.is_empty(), "Stack should be empty: final_buf={:?} stack={:?}", final_buf, stack);
463-
AttrTokenStream::new(final_buf.inner)
478+
panic!("Missing final buf!")
464479
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
macro_rules! values {
2+
($($token:ident($value:literal) $(as $inner:ty)? => $attr:meta,)*) => {
3+
#[derive(Debug)]
4+
pub enum TokenKind {
5+
$(
6+
#[$attr]
7+
$token $($inner)? = $value,
8+
)*
9+
}
10+
};
11+
}
12+
//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)`
13+
//~| ERROR macro expansion ignores token `(String)` and any following
14+
15+
values!(STRING(1) as (String) => cfg(test),);
16+
17+
fn main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)`
2+
--> $DIR/syntax-error-recovery.rs:7:26
3+
|
4+
LL | $token $($inner)? = $value,
5+
| ^^^^^^ expected one of `(`, `,`, `=`, `{`, or `}`
6+
...
7+
LL | values!(STRING(1) as (String) => cfg(test),);
8+
| -------------------------------------------- in this macro invocation
9+
|
10+
= note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
12+
error: macro expansion ignores token `(String)` and any following
13+
--> $DIR/syntax-error-recovery.rs:7:26
14+
|
15+
LL | $token $($inner)? = $value,
16+
| ^^^^^^
17+
...
18+
LL | values!(STRING(1) as (String) => cfg(test),);
19+
| -------------------------------------------- caused by the macro expansion here
20+
|
21+
= note: the usage of `values!` is likely invalid in item context
22+
23+
error: aborting due to 2 previous errors
24+

0 commit comments

Comments
 (0)