Skip to content

Commit 632fa8e

Browse files
committed
Fix TokenStream::from_str for input consisting of a single Group
TokenStream holds a `tt::Subtree` but assumes its `delimiter` is always `None`. In particular, the iterator implementation iterates over the inner `token_trees` and ignores the `delimiter`. However, `TokenStream::from_str` violated this assumption when the input consists of a single Group by producing a Subtree with an outer delimiter, which was ignored as seen by a procedural macro. In this case, wrap an extra level of Subtree around it. Fixes #7810 Fixes #7875
1 parent 750d3cb commit 632fa8e

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

crates/proc_macro_srv/src/rustc_server.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,16 @@ impl TokenStream {
3434
}
3535

3636
pub fn with_subtree(subtree: tt::Subtree) -> Self {
37-
TokenStream { subtree }
37+
if subtree.delimiter.is_some() {
38+
TokenStream {
39+
subtree: tt::Subtree {
40+
token_trees: vec![TokenTree::Subtree(subtree)],
41+
delimiter: None,
42+
},
43+
}
44+
} else {
45+
TokenStream { subtree }
46+
}
3847
}
3948

4049
pub fn is_empty(&self) -> bool {
@@ -185,7 +194,7 @@ pub mod token_stream {
185194
mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?;
186195

187196
let subtree = subtree_replace_token_ids_with_unspecified(subtree);
188-
Ok(TokenStream { subtree })
197+
Ok(TokenStream::with_subtree(subtree))
189198
}
190199
}
191200

@@ -779,4 +788,27 @@ mod tests {
779788

780789
assert_eq!(s.to_string(), "struct T {}");
781790
}
791+
792+
#[test]
793+
fn test_rustc_server_from_str() {
794+
use std::str::FromStr;
795+
let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
796+
delimiter: Some(tt::Delimiter {
797+
id: tt::TokenId::unspecified(),
798+
kind: tt::DelimiterKind::Parenthesis,
799+
}),
800+
token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
801+
text: "a".into(),
802+
id: tt::TokenId::unspecified(),
803+
}))],
804+
});
805+
806+
let t1 = TokenStream::from_str("(a)").unwrap();
807+
assert_eq!(t1.subtree.token_trees.len(), 1);
808+
assert_eq!(t1.subtree.token_trees[0], subtree_paren_a);
809+
810+
let t2 = TokenStream::from_str("(a);").unwrap();
811+
assert_eq!(t2.subtree.token_trees.len(), 2);
812+
assert_eq!(t2.subtree.token_trees[0], subtree_paren_a);
813+
}
782814
}

0 commit comments

Comments
 (0)