Skip to content

Commit 44acb1d

Browse files
authored
Rollup merge of rust-lang#65455 - nnethercote:avoid-unnecessary-TokenTree-to-TokenStream-conversions, r=petrochenkov
Avoid unnecessary `TokenTree` to `TokenStream` conversions A `TokenStream` contains any number of `TokenTrees`. Therefore, a single `TokenTree` can be promoted to a `TokenStream`. But doing so costs two allocations: one for the single-element `Vec`, and one for the `Lrc`. (An `IsJoint` value also must be added; the default is `NonJoint`.) The current code converts `TokenTree`s to `TokenStream`s unnecessarily in a few places. This PR removes some of these unnecessary conversions, both simplifying the code and speeding it up. r? @petrochenkov
2 parents f859526 + e4ec4a6 commit 44acb1d

File tree

5 files changed

+41
-36
lines changed

5 files changed

+41
-36
lines changed

src/libsyntax/attr/mod.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::ptr::P;
2222
use crate::sess::ParseSess;
2323
use crate::symbol::{sym, Symbol};
2424
use crate::ThinVec;
25-
use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
25+
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
2626
use crate::GLOBALS;
2727

2828
use log::debug;
@@ -463,7 +463,7 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option
463463
}
464464

465465
impl MetaItem {
466-
fn tokens(&self) -> TokenStream {
466+
fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
467467
let mut idents = vec![];
468468
let mut last_pos = BytePos(0 as u32);
469469
for (i, segment) in self.path.segments.iter().enumerate() {
@@ -477,8 +477,8 @@ impl MetaItem {
477477
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
478478
last_pos = segment.ident.span.hi();
479479
}
480-
self.kind.tokens(self.span).append_to_tree_and_joint_vec(&mut idents);
481-
TokenStream::new(idents)
480+
idents.extend(self.kind.token_trees_and_joints(self.span));
481+
idents
482482
}
483483

484484
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItem>
@@ -537,31 +537,41 @@ impl MetaItem {
537537
}
538538

539539
impl MetaItemKind {
540-
pub fn tokens(&self, span: Span) -> TokenStream {
540+
pub fn token_trees_and_joints(&self, span: Span) -> Vec<TreeAndJoint> {
541541
match *self {
542-
MetaItemKind::Word => TokenStream::default(),
542+
MetaItemKind::Word => vec![],
543543
MetaItemKind::NameValue(ref lit) => {
544-
let mut vec = vec![TokenTree::token(token::Eq, span).into()];
545-
lit.tokens().append_to_tree_and_joint_vec(&mut vec);
546-
TokenStream::new(vec)
544+
vec![
545+
TokenTree::token(token::Eq, span).into(),
546+
lit.token_tree().into(),
547+
]
547548
}
548549
MetaItemKind::List(ref list) => {
549550
let mut tokens = Vec::new();
550551
for (i, item) in list.iter().enumerate() {
551552
if i > 0 {
552553
tokens.push(TokenTree::token(token::Comma, span).into());
553554
}
554-
item.tokens().append_to_tree_and_joint_vec(&mut tokens);
555+
tokens.extend(item.token_trees_and_joints())
555556
}
556-
TokenTree::Delimited(
557-
DelimSpan::from_single(span),
558-
token::Paren,
559-
TokenStream::new(tokens).into(),
560-
).into()
557+
vec![
558+
TokenTree::Delimited(
559+
DelimSpan::from_single(span),
560+
token::Paren,
561+
TokenStream::new(tokens).into(),
562+
).into()
563+
]
561564
}
562565
}
563566
}
564567

568+
// Premature conversions of `TokenTree`s to `TokenStream`s can hurt
569+
// performance. Do not use this function if `token_trees_and_joints()` can
570+
// be used instead.
571+
pub fn tokens(&self, span: Span) -> TokenStream {
572+
TokenStream::new(self.token_trees_and_joints(span))
573+
}
574+
565575
fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<MetaItemKind>
566576
where I: Iterator<Item = TokenTree>,
567577
{
@@ -603,10 +613,10 @@ impl NestedMetaItem {
603613
}
604614
}
605615

606-
fn tokens(&self) -> TokenStream {
616+
fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
607617
match *self {
608-
NestedMetaItem::MetaItem(ref item) => item.tokens(),
609-
NestedMetaItem::Literal(ref lit) => lit.tokens(),
618+
NestedMetaItem::MetaItem(ref item) => item.token_trees_and_joints(),
619+
NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()],
610620
}
611621
}
612622

src/libsyntax/parse/literal.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::ast::{self, Lit, LitKind};
44
use crate::parse::token::{self, Token};
55
use crate::symbol::{kw, sym, Symbol};
6-
use crate::tokenstream::{TokenStream, TokenTree};
6+
use crate::tokenstream::TokenTree;
77

88
use log::debug;
99
use rustc_data_structures::sync::Lrc;
@@ -216,13 +216,13 @@ impl Lit {
216216
Lit { token: kind.to_lit_token(), kind, span }
217217
}
218218

219-
/// Losslessly convert an AST literal into a token stream.
220-
crate fn tokens(&self) -> TokenStream {
219+
/// Losslessly convert an AST literal into a token tree.
220+
crate fn token_tree(&self) -> TokenTree {
221221
let token = match self.token.kind {
222222
token::Bool => token::Ident(self.token.symbol, false),
223223
_ => token::Literal(self.token),
224224
};
225-
TokenTree::token(token, self.span).into()
225+
TokenTree::token(token, self.span)
226226
}
227227
}
228228

src/libsyntax/parse/parser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,10 @@ impl TokenCursor {
285285
token::NoDelim,
286286
&if doc_comment_style(&name.as_str()) == AttrStyle::Inner {
287287
[TokenTree::token(token::Pound, sp), TokenTree::token(token::Not, sp), body]
288-
.iter().cloned().collect::<TokenStream>().into()
288+
.iter().cloned().collect::<TokenStream>()
289289
} else {
290290
[TokenTree::token(token::Pound, sp), body]
291-
.iter().cloned().collect::<TokenStream>().into()
291+
.iter().cloned().collect::<TokenStream>()
292292
},
293293
)));
294294

src/libsyntax/parse/parser/attr.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::tokenstream::{TokenStream, TokenTree};
66
use crate::source_map::Span;
77

88
use log::debug;
9-
use smallvec::smallvec;
109

1110
#[derive(Debug)]
1211
enum InnerAttributeParsePolicy<'a> {
@@ -193,15 +192,15 @@ impl<'a> Parser<'a> {
193192
is_interpolated_expr = true;
194193
}
195194
}
196-
let tokens = if is_interpolated_expr {
195+
let token_tree = if is_interpolated_expr {
197196
// We need to accept arbitrary interpolated expressions to continue
198197
// supporting things like `doc = $expr` that work on stable.
199198
// Non-literal interpolated expressions are rejected after expansion.
200-
self.parse_token_tree().into()
199+
self.parse_token_tree()
201200
} else {
202-
self.parse_unsuffixed_lit()?.tokens()
201+
self.parse_unsuffixed_lit()?.token_tree()
203202
};
204-
TokenStream::from_streams(smallvec![eq.into(), tokens])
203+
TokenStream::new(vec![eq.into(), token_tree.into()])
205204
} else {
206205
TokenStream::default()
207206
};

src/libsyntax/tokenstream.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ impl From<TokenTree> for TreeAndJoint {
202202
}
203203
}
204204

205-
impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
206-
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
207-
TokenStream::from_streams(iter.into_iter().map(Into::into).collect::<SmallVec<_>>())
205+
impl iter::FromIterator<TokenTree> for TokenStream {
206+
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
207+
TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TreeAndJoint>>())
208208
}
209209
}
210210

@@ -271,10 +271,6 @@ impl TokenStream {
271271
}
272272
}
273273

274-
pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
275-
vec.extend(self.0.iter().cloned());
276-
}
277-
278274
pub fn trees(&self) -> Cursor {
279275
self.clone().into_trees()
280276
}

0 commit comments

Comments
 (0)