Skip to content

Commit

Permalink
When snapshoting a TokenCursor, preserve the top frame of the stack
Browse files Browse the repository at this point in the history
If we start capturing on the first token of a frame,
we can legally pop the frame (e.g. we can capture something like
'{ my_tokens } other_tokens'. As a result, we need to snapshot the frame
at the top of the current stack, rather than just using an empty stack.

Fixes taiki-e/pin-project#312
  • Loading branch information
Aaron1011 committed Jan 24, 2021
1 parent 9a9477f commit 29bb1cb
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
8 changes: 5 additions & 3 deletions compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,9 +1260,11 @@ impl<'a> Parser<'a> {
let start_token = (self.token.clone(), self.token_spacing);
let cursor_snapshot = TokenCursor {
frame: self.token_cursor.frame.clone(),
// We only ever capture tokens within our current frame,
// so we can just use an empty frame stack
stack: vec![],
// If we start collecting on the first token of a frame
// (e.g. the '{' in '{ my_tokens }'), then we can legally
// exit the frame (e.g. collecting '{ my_tokens } something_else'
// Therefore, we preserve the top of the stack, but nothing else
stack: self.token_cursor.stack.first().cloned().into_iter().collect(),
desugar_doc_comments: self.token_cursor.desugar_doc_comments,
num_next_calls: self.token_cursor.num_next_calls,
append_unglued_token: self.token_cursor.append_unglued_token.clone(),
Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// force-host
// no-prefer-dynamic

#![crate_type = "proc-macro"]
#![feature(proc_macro_quote)]

extern crate proc_macro;
use proc_macro::{TokenStream, quote};

#[proc_macro_attribute]
pub fn first_attr(_: TokenStream, input: TokenStream) -> TokenStream {
let recollected: TokenStream = input.into_iter().collect();
quote! {
#[second_attr]
$recollected
}
}

#[proc_macro_attribute]
pub fn second_attr(_: TokenStream, input: TokenStream) -> TokenStream {
let _recollected: TokenStream = input.into_iter().collect();
TokenStream::new()
}
17 changes: 17 additions & 0 deletions src/test/ui/proc-macro/nonterminal-recollect-attr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// check-pass
// aux-build:nonterminal-recollect-attr.rs

extern crate nonterminal_recollect_attr;
use nonterminal_recollect_attr::*;

macro_rules! my_macro {
($v:ident) => {
#[first_attr]
$v struct Foo {
field: u8
}
}
}

my_macro!(pub);
fn main() {}

0 comments on commit 29bb1cb

Please sign in to comment.