Skip to content

Commit 679335a

Browse files
committed
proc_macro: reduce the number of messages required to create, extend, and iterate TokenStreams
This significantly reduces the cost of common interactions with TokenStream when running with the CrossThread execution strategy, by reducing the number of RPC calls required.
1 parent 287d988 commit 679335a

File tree

4 files changed

+74
-52
lines changed

4 files changed

+74
-52
lines changed

proc_macro/src/bridge/client.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,6 @@ define_handles! {
178178
'owned:
179179
FreeFunctions,
180180
TokenStream,
181-
TokenStreamBuilder,
182-
TokenStreamIter,
183181
Group,
184182
Literal,
185183
SourceFile,
@@ -204,12 +202,6 @@ impl Clone for TokenStream {
204202
}
205203
}
206204

207-
impl Clone for TokenStreamIter {
208-
fn clone(&self) -> Self {
209-
self.clone()
210-
}
211-
}
212-
213205
impl Clone for Group {
214206
fn clone(&self) -> Self {
215207
self.clone()
@@ -435,7 +427,11 @@ impl Client<crate::TokenStream, crate::TokenStream> {
435427
Client {
436428
get_handle_counters: HandleCounters::get,
437429
run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
438-
run_client(bridge, |input| f(crate::TokenStream(input)).0)
430+
run_client(bridge, |input| {
431+
f(crate::TokenStream(Some(input)))
432+
.0
433+
.unwrap_or_else(|| TokenStream::concat_streams(None, vec![]))
434+
})
439435
}),
440436
_marker: PhantomData,
441437
}
@@ -450,7 +446,9 @@ impl Client<(crate::TokenStream, crate::TokenStream), crate::TokenStream> {
450446
get_handle_counters: HandleCounters::get,
451447
run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
452448
run_client(bridge, |(input, input2)| {
453-
f(crate::TokenStream(input), crate::TokenStream(input2)).0
449+
f(crate::TokenStream(Some(input)), crate::TokenStream(Some(input2)))
450+
.0
451+
.unwrap_or_else(|| TokenStream::concat_streams(None, vec![]))
454452
})
455453
}),
456454
_marker: PhantomData,

proc_macro/src/bridge/mod.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,33 +60,29 @@ macro_rules! with_api {
6060
TokenStream {
6161
fn drop($self: $S::TokenStream);
6262
fn clone($self: &$S::TokenStream) -> $S::TokenStream;
63-
fn new() -> $S::TokenStream;
6463
fn is_empty($self: &$S::TokenStream) -> bool;
6564
fn expand_expr($self: &$S::TokenStream) -> Result<$S::TokenStream, ()>;
6665
fn from_str(src: &str) -> $S::TokenStream;
6766
fn to_string($self: &$S::TokenStream) -> String;
6867
fn from_token_tree(
6968
tree: TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>,
7069
) -> $S::TokenStream;
71-
fn into_iter($self: $S::TokenStream) -> $S::TokenStreamIter;
72-
},
73-
TokenStreamBuilder {
74-
fn drop($self: $S::TokenStreamBuilder);
75-
fn new() -> $S::TokenStreamBuilder;
76-
fn push($self: &mut $S::TokenStreamBuilder, stream: $S::TokenStream);
77-
fn build($self: $S::TokenStreamBuilder) -> $S::TokenStream;
78-
},
79-
TokenStreamIter {
80-
fn drop($self: $S::TokenStreamIter);
81-
fn clone($self: &$S::TokenStreamIter) -> $S::TokenStreamIter;
82-
fn next(
83-
$self: &mut $S::TokenStreamIter,
84-
) -> Option<TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>>;
70+
fn concat_trees(
71+
base: Option<$S::TokenStream>,
72+
trees: Vec<TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>>,
73+
) -> $S::TokenStream;
74+
fn concat_streams(
75+
base: Option<$S::TokenStream>,
76+
trees: Vec<$S::TokenStream>,
77+
) -> $S::TokenStream;
78+
fn into_iter(
79+
$self: $S::TokenStream
80+
) -> Vec<TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>>;
8581
},
8682
Group {
8783
fn drop($self: $S::Group);
8884
fn clone($self: &$S::Group) -> $S::Group;
89-
fn new(delimiter: Delimiter, stream: $S::TokenStream) -> $S::Group;
85+
fn new(delimiter: Delimiter, stream: Option<$S::TokenStream>) -> $S::Group;
9086
fn delimiter($self: &$S::Group) -> Delimiter;
9187
fn stream($self: &$S::Group) -> $S::TokenStream;
9288
fn span($self: &$S::Group) -> $S::Span;

proc_macro/src/bridge/server.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use super::client::HandleStore;
88
pub trait Types {
99
type FreeFunctions: 'static;
1010
type TokenStream: 'static + Clone;
11-
type TokenStreamBuilder: 'static;
12-
type TokenStreamIter: 'static + Clone;
1311
type Group: 'static + Clone;
1412
type Punct: 'static + Copy + Eq + Hash;
1513
type Ident: 'static + Copy + Eq + Hash;

proc_macro/src/lib.rs

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use std::cmp::Ordering;
4343
use std::ops::RangeBounds;
4444
use std::path::PathBuf;
4545
use std::str::FromStr;
46-
use std::{error, fmt, iter, mem};
46+
use std::{error, fmt, iter};
4747

4848
/// Determines whether proc_macro has been made accessible to the currently
4949
/// running program.
@@ -72,7 +72,7 @@ pub fn is_available() -> bool {
7272
/// and `#[proc_macro_derive]` definitions.
7373
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
7474
#[derive(Clone)]
75-
pub struct TokenStream(bridge::client::TokenStream);
75+
pub struct TokenStream(Option<bridge::client::TokenStream>);
7676

7777
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
7878
impl !Send for TokenStream {}
@@ -126,13 +126,13 @@ impl TokenStream {
126126
/// Returns an empty `TokenStream` containing no token trees.
127127
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
128128
pub fn new() -> TokenStream {
129-
TokenStream(bridge::client::TokenStream::new())
129+
TokenStream(None)
130130
}
131131

132132
/// Checks if this `TokenStream` is empty.
133133
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
134134
pub fn is_empty(&self) -> bool {
135-
self.0.is_empty()
135+
self.0.as_ref().map(|h| h.is_empty()).unwrap_or(true)
136136
}
137137

138138
/// Parses this `TokenStream` as an expression and attempts to expand any
@@ -147,8 +147,9 @@ impl TokenStream {
147147
/// considered errors, is unspecified and may change in the future.
148148
#[unstable(feature = "proc_macro_expand", issue = "90765")]
149149
pub fn expand_expr(&self) -> Result<TokenStream, ExpandError> {
150-
match bridge::client::TokenStream::expand_expr(&self.0) {
151-
Ok(stream) => Ok(TokenStream(stream)),
150+
let stream = self.0.as_ref().ok_or(ExpandError)?;
151+
match bridge::client::TokenStream::expand_expr(stream) {
152+
Ok(stream) => Ok(TokenStream(Some(stream))),
152153
Err(_) => Err(ExpandError),
153154
}
154155
}
@@ -166,7 +167,7 @@ impl FromStr for TokenStream {
166167
type Err = LexError;
167168

168169
fn from_str(src: &str) -> Result<TokenStream, LexError> {
169-
Ok(TokenStream(bridge::client::TokenStream::from_str(src)))
170+
Ok(TokenStream(Some(bridge::client::TokenStream::from_str(src))))
170171
}
171172
}
172173

@@ -175,7 +176,7 @@ impl FromStr for TokenStream {
175176
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
176177
impl ToString for TokenStream {
177178
fn to_string(&self) -> String {
178-
self.0.to_string()
179+
self.0.as_ref().map(|t| t.to_string()).unwrap_or_default()
179180
}
180181
}
181182

@@ -208,24 +209,38 @@ impl Default for TokenStream {
208209
#[unstable(feature = "proc_macro_quote", issue = "54722")]
209210
pub use quote::{quote, quote_span};
210211

212+
fn tree_to_bridge_tree(
213+
tree: TokenTree,
214+
) -> bridge::TokenTree<
215+
bridge::client::Group,
216+
bridge::client::Punct,
217+
bridge::client::Ident,
218+
bridge::client::Literal,
219+
> {
220+
match tree {
221+
TokenTree::Group(tt) => bridge::TokenTree::Group(tt.0),
222+
TokenTree::Punct(tt) => bridge::TokenTree::Punct(tt.0),
223+
TokenTree::Ident(tt) => bridge::TokenTree::Ident(tt.0),
224+
TokenTree::Literal(tt) => bridge::TokenTree::Literal(tt.0),
225+
}
226+
}
227+
211228
/// Creates a token stream containing a single token tree.
212229
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
213230
impl From<TokenTree> for TokenStream {
214231
fn from(tree: TokenTree) -> TokenStream {
215-
TokenStream(bridge::client::TokenStream::from_token_tree(match tree {
216-
TokenTree::Group(tt) => bridge::TokenTree::Group(tt.0),
217-
TokenTree::Punct(tt) => bridge::TokenTree::Punct(tt.0),
218-
TokenTree::Ident(tt) => bridge::TokenTree::Ident(tt.0),
219-
TokenTree::Literal(tt) => bridge::TokenTree::Literal(tt.0),
220-
}))
232+
TokenStream(Some(bridge::client::TokenStream::from_token_tree(tree_to_bridge_tree(tree))))
221233
}
222234
}
223235

224236
/// Collects a number of token trees into a single stream.
225237
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
226238
impl iter::FromIterator<TokenTree> for TokenStream {
227239
fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
228-
trees.into_iter().map(TokenStream::from).collect()
240+
TokenStream(Some(bridge::client::TokenStream::concat_trees(
241+
None,
242+
trees.into_iter().map(tree_to_bridge_tree).collect(),
243+
)))
229244
}
230245
}
231246

@@ -234,24 +249,30 @@ impl iter::FromIterator<TokenTree> for TokenStream {
234249
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
235250
impl iter::FromIterator<TokenStream> for TokenStream {
236251
fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
237-
let mut builder = bridge::client::TokenStreamBuilder::new();
238-
streams.into_iter().for_each(|stream| builder.push(stream.0));
239-
TokenStream(builder.build())
252+
TokenStream(Some(bridge::client::TokenStream::concat_streams(
253+
None,
254+
streams.into_iter().filter_map(|stream| stream.0).collect(),
255+
)))
240256
}
241257
}
242258

243259
#[stable(feature = "token_stream_extend", since = "1.30.0")]
244260
impl Extend<TokenTree> for TokenStream {
245261
fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
246-
self.extend(trees.into_iter().map(TokenStream::from));
262+
*self = TokenStream(Some(bridge::client::TokenStream::concat_trees(
263+
self.0.take(),
264+
trees.into_iter().map(|tree| tree_to_bridge_tree(tree)).collect(),
265+
)));
247266
}
248267
}
249268

250269
#[stable(feature = "token_stream_extend", since = "1.30.0")]
251270
impl Extend<TokenStream> for TokenStream {
252271
fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
253-
// FIXME(eddyb) Use an optimized implementation if/when possible.
254-
*self = iter::once(mem::replace(self, Self::new())).chain(streams).collect();
272+
*self = TokenStream(Some(bridge::client::TokenStream::concat_streams(
273+
self.0.take(),
274+
streams.into_iter().filter_map(|stream| stream.0).collect(),
275+
)));
255276
}
256277
}
257278

@@ -265,7 +286,16 @@ pub mod token_stream {
265286
/// and returns whole groups as token trees.
266287
#[derive(Clone)]
267288
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
268-
pub struct IntoIter(bridge::client::TokenStreamIter);
289+
pub struct IntoIter(
290+
std::vec::IntoIter<
291+
bridge::TokenTree<
292+
bridge::client::Group,
293+
bridge::client::Punct,
294+
bridge::client::Ident,
295+
bridge::client::Literal,
296+
>,
297+
>,
298+
);
269299

270300
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
271301
impl Iterator for IntoIter {
@@ -287,7 +317,7 @@ pub mod token_stream {
287317
type IntoIter = IntoIter;
288318

289319
fn into_iter(self) -> IntoIter {
290-
IntoIter(self.0.into_iter())
320+
IntoIter(self.0.map(|v| v.into_iter()).unwrap_or_default().into_iter())
291321
}
292322
}
293323
}
@@ -734,7 +764,7 @@ impl Group {
734764
/// returned above.
735765
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
736766
pub fn stream(&self) -> TokenStream {
737-
TokenStream(self.0.stream())
767+
TokenStream(Some(self.0.stream()))
738768
}
739769

740770
/// Returns the span for the delimiters of this token stream, spanning the

0 commit comments

Comments
 (0)