Skip to content

Commit 62f594b

Browse files
committed
Refactor TokenStream to hold Vec<TokenTree> instead of tt::Subtree
`TokenStream` assumes that its subtree's delimeter is `None`, and this should be encoded in the type system instead of having a delimiter field that is mostly ignored. `tt::Subtree` is just `pub delimiter: Option<Delimiter>, pub token_trees: Vec<TokenTree>`, so a Subtree that is statically guaranteed not to have a delimiter is just Vec<TokenTree>.
1 parent 632fa8e commit 62f594b

File tree

3 files changed

+56
-65
lines changed

3 files changed

+56
-65
lines changed

crates/proc_macro_srv/src/dylib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl Expander {
138138
parsed_body,
139139
false,
140140
);
141-
return res.map(|it| it.subtree);
141+
return res.map(|it| it.into_subtree());
142142
}
143143
bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
144144
let res = client.run(
@@ -147,7 +147,7 @@ impl Expander {
147147
parsed_body,
148148
false,
149149
);
150-
return res.map(|it| it.subtree);
150+
return res.map(|it| it.into_subtree());
151151
}
152152
bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
153153
let res = client.run(
@@ -157,7 +157,7 @@ impl Expander {
157157
parsed_body,
158158
false,
159159
);
160-
return res.map(|it| it.subtree);
160+
return res.map(|it| it.into_subtree());
161161
}
162162
_ => continue,
163163
}

crates/proc_macro_srv/src/rustc_server.rs

Lines changed: 52 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,35 @@ type Span = tt::TokenId;
2525

2626
#[derive(Debug, Clone)]
2727
pub struct TokenStream {
28-
pub subtree: tt::Subtree,
28+
pub token_trees: Vec<TokenTree>,
2929
}
3030

3131
impl TokenStream {
3232
pub fn new() -> Self {
33-
TokenStream { subtree: Default::default() }
33+
TokenStream { token_trees: Default::default() }
3434
}
3535

3636
pub fn with_subtree(subtree: tt::Subtree) -> Self {
3737
if subtree.delimiter.is_some() {
38-
TokenStream {
39-
subtree: tt::Subtree {
40-
token_trees: vec![TokenTree::Subtree(subtree)],
41-
delimiter: None,
42-
},
43-
}
38+
TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
4439
} else {
45-
TokenStream { subtree }
40+
TokenStream { token_trees: subtree.token_trees }
4641
}
4742
}
4843

44+
pub fn into_subtree(self) -> tt::Subtree {
45+
tt::Subtree { delimiter: None, token_trees: self.token_trees }
46+
}
47+
4948
pub fn is_empty(&self) -> bool {
50-
self.subtree.token_trees.is_empty()
49+
self.token_trees.is_empty()
5150
}
5251
}
5352

5453
/// Creates a token stream containing a single token tree.
5554
impl From<TokenTree> for TokenStream {
5655
fn from(tree: TokenTree) -> TokenStream {
57-
TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } }
56+
TokenStream { token_trees: vec![tree] }
5857
}
5958
}
6059

@@ -87,10 +86,10 @@ impl Extend<TokenStream> for TokenStream {
8786
for tkn in item {
8887
match tkn {
8988
tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
90-
self.subtree.token_trees.extend(subtree.token_trees);
89+
self.token_trees.extend(subtree.token_trees);
9190
}
9291
_ => {
93-
self.subtree.token_trees.push(tkn);
92+
self.token_trees.push(tkn);
9493
}
9594
}
9695
}
@@ -173,7 +172,7 @@ pub mod token_stream {
173172
type IntoIter = super::IntoIter<TokenTree>;
174173

175174
fn into_iter(self) -> Self::IntoIter {
176-
self.subtree.token_trees.into_iter()
175+
self.token_trees.into_iter()
177176
}
178177
}
179178

@@ -200,32 +199,32 @@ pub mod token_stream {
200199

201200
impl ToString for TokenStream {
202201
fn to_string(&self) -> String {
203-
let tt = self.subtree.clone().into();
204-
to_text(&tt)
202+
tokentrees_to_text(&self.token_trees[..])
205203
}
206204
}
207205

208-
fn to_text(tkn: &tt::TokenTree) -> String {
206+
fn tokentrees_to_text(tkns: &[tt::TokenTree]) -> String {
207+
tkns.iter()
208+
.fold((String::new(), true), |(last, last_to_joint), tkn| {
209+
let s = [last, tokentree_to_text(tkn)].join(if last_to_joint { "" } else { " " });
210+
let mut is_joint = false;
211+
if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
212+
if punct.spacing == tt::Spacing::Joint {
213+
is_joint = true;
214+
}
215+
}
216+
(s, is_joint)
217+
})
218+
.0
219+
}
220+
221+
fn tokentree_to_text(tkn: &tt::TokenTree) -> String {
209222
match tkn {
210223
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
211224
tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
212225
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
213226
tt::TokenTree::Subtree(subtree) => {
214-
let content = subtree
215-
.token_trees
216-
.iter()
217-
.fold((String::new(), true), |(last, last_to_joint), tkn| {
218-
let s = [last, to_text(tkn)].join(if last_to_joint { "" } else { " " });
219-
let mut is_joint = false;
220-
if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
221-
if punct.spacing == tt::Spacing::Joint {
222-
is_joint = true;
223-
}
224-
}
225-
(s, is_joint)
226-
})
227-
.0;
228-
227+
let content = tokentrees_to_text(&subtree.token_trees);
229228
let (open, close) = match subtree.delimiter.map(|it| it.kind) {
230229
None => ("", ""),
231230
Some(tt::DelimiterKind::Brace) => ("{", "}"),
@@ -442,20 +441,15 @@ fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
442441

443442
impl server::Group for Rustc {
444443
fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group {
445-
Self::Group {
446-
delimiter: delim_to_internal(delimiter),
447-
token_trees: stream.subtree.token_trees,
448-
}
444+
Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees }
449445
}
450446
fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
451447
delim_to_external(group.delimiter)
452448
}
453449

454450
// NOTE: Return value of do not include delimiter
455451
fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
456-
TokenStream {
457-
subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() },
458-
}
452+
TokenStream { token_trees: group.token_trees.clone() }
459453
}
460454

461455
fn span(&mut self, group: &Self::Group) -> Self::Span {
@@ -764,26 +758,23 @@ mod tests {
764758
#[test]
765759
fn test_rustc_server_to_string() {
766760
let s = TokenStream {
767-
subtree: tt::Subtree {
768-
delimiter: None,
769-
token_trees: vec![
770-
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
771-
text: "struct".into(),
772-
id: tt::TokenId::unspecified(),
773-
})),
774-
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
775-
text: "T".into(),
761+
token_trees: vec![
762+
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
763+
text: "struct".into(),
764+
id: tt::TokenId::unspecified(),
765+
})),
766+
tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
767+
text: "T".into(),
768+
id: tt::TokenId::unspecified(),
769+
})),
770+
tt::TokenTree::Subtree(tt::Subtree {
771+
delimiter: Some(tt::Delimiter {
776772
id: tt::TokenId::unspecified(),
777-
})),
778-
tt::TokenTree::Subtree(tt::Subtree {
779-
delimiter: Some(tt::Delimiter {
780-
id: tt::TokenId::unspecified(),
781-
kind: tt::DelimiterKind::Brace,
782-
}),
783-
token_trees: vec![],
773+
kind: tt::DelimiterKind::Brace,
784774
}),
785-
],
786-
},
775+
token_trees: vec![],
776+
}),
777+
],
787778
};
788779

789780
assert_eq!(s.to_string(), "struct T {}");
@@ -804,11 +795,11 @@ mod tests {
804795
});
805796

806797
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);
798+
assert_eq!(t1.token_trees.len(), 1);
799+
assert_eq!(t1.token_trees[0], subtree_paren_a);
809800

810801
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);
802+
assert_eq!(t2.token_trees.len(), 2);
803+
assert_eq!(t2.token_trees[0], subtree_paren_a);
813804
}
814805
}

crates/proc_macro_srv/src/tests/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub fn assert_expand(
5252
let expander = dylib::Expander::new(&path).unwrap();
5353
let fixture = parse_string(ra_fixture).unwrap();
5454

55-
let res = expander.expand(macro_name, &fixture.subtree, None).unwrap();
55+
let res = expander.expand(macro_name, &fixture.into_subtree(), None).unwrap();
5656
assert_eq_text!(&expect.trim(), &format!("{:?}", res));
5757
}
5858

0 commit comments

Comments
 (0)