@@ -10,10 +10,20 @@ use crate::{fallback, Delimiter, Punct, Spacing, TokenTree};
10
10
11
11
#[ derive( Clone ) ]
12
12
pub enum TokenStream {
13
- Compiler ( proc_macro :: TokenStream ) ,
13
+ Compiler ( DeferredTokenStream ) ,
14
14
Fallback ( fallback:: TokenStream ) ,
15
15
}
16
16
17
+ // Work around https://github.com/rust-lang/rust/issues/65080.
18
+ // In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote,
19
+ // we hold on to the appended tokens and do proc_macro::TokenStream::extend as
20
+ // late as possible to batch together consecutive uses of the Extend impl.
21
+ #[ derive( Clone ) ]
22
+ pub struct DeferredTokenStream {
23
+ stream : proc_macro:: TokenStream ,
24
+ extra : Vec < proc_macro:: TokenTree > ,
25
+ }
26
+
17
27
pub enum LexError {
18
28
Compiler ( proc_macro:: LexError ) ,
19
29
Fallback ( fallback:: LexError ) ,
@@ -80,10 +90,32 @@ fn mismatch() -> ! {
80
90
panic ! ( "stable/nightly mismatch" )
81
91
}
82
92
93
+ impl DeferredTokenStream {
94
+ fn new ( stream : proc_macro:: TokenStream ) -> Self {
95
+ DeferredTokenStream {
96
+ stream,
97
+ extra : Vec :: new ( ) ,
98
+ }
99
+ }
100
+
101
+ fn is_empty ( & self ) -> bool {
102
+ self . stream . is_empty ( ) && self . extra . is_empty ( )
103
+ }
104
+
105
+ fn evaluate_now ( & mut self ) {
106
+ self . stream . extend ( self . extra . drain ( ..) ) ;
107
+ }
108
+
109
+ fn into_token_stream ( mut self ) -> proc_macro:: TokenStream {
110
+ self . evaluate_now ( ) ;
111
+ self . stream
112
+ }
113
+ }
114
+
83
115
impl TokenStream {
84
116
pub fn new ( ) -> TokenStream {
85
117
if nightly_works ( ) {
86
- TokenStream :: Compiler ( proc_macro:: TokenStream :: new ( ) )
118
+ TokenStream :: Compiler ( DeferredTokenStream :: new ( proc_macro:: TokenStream :: new ( ) ) )
87
119
} else {
88
120
TokenStream :: Fallback ( fallback:: TokenStream :: new ( ) )
89
121
}
@@ -98,7 +130,7 @@ impl TokenStream {
98
130
99
131
fn unwrap_nightly ( self ) -> proc_macro:: TokenStream {
100
132
match self {
101
- TokenStream :: Compiler ( s) => s,
133
+ TokenStream :: Compiler ( s) => s. into_token_stream ( ) ,
102
134
TokenStream :: Fallback ( _) => mismatch ( ) ,
103
135
}
104
136
}
@@ -116,7 +148,9 @@ impl FromStr for TokenStream {
116
148
117
149
fn from_str ( src : & str ) -> Result < TokenStream , LexError > {
118
150
if nightly_works ( ) {
119
- Ok ( TokenStream :: Compiler ( src. parse ( ) ?) )
151
+ Ok ( TokenStream :: Compiler ( DeferredTokenStream :: new (
152
+ src. parse ( ) ?,
153
+ ) ) )
120
154
} else {
121
155
Ok ( TokenStream :: Fallback ( src. parse ( ) ?) )
122
156
}
@@ -126,22 +160,22 @@ impl FromStr for TokenStream {
126
160
impl fmt:: Display for TokenStream {
127
161
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
128
162
match self {
129
- TokenStream :: Compiler ( tts) => tts. fmt ( f) ,
163
+ TokenStream :: Compiler ( tts) => tts. clone ( ) . into_token_stream ( ) . fmt ( f) ,
130
164
TokenStream :: Fallback ( tts) => tts. fmt ( f) ,
131
165
}
132
166
}
133
167
}
134
168
135
169
impl From < proc_macro:: TokenStream > for TokenStream {
136
170
fn from ( inner : proc_macro:: TokenStream ) -> TokenStream {
137
- TokenStream :: Compiler ( inner)
171
+ TokenStream :: Compiler ( DeferredTokenStream :: new ( inner) )
138
172
}
139
173
}
140
174
141
175
impl From < TokenStream > for proc_macro:: TokenStream {
142
176
fn from ( inner : TokenStream ) -> proc_macro:: TokenStream {
143
177
match inner {
144
- TokenStream :: Compiler ( inner) => inner,
178
+ TokenStream :: Compiler ( inner) => inner. into_token_stream ( ) ,
145
179
TokenStream :: Fallback ( inner) => inner. to_string ( ) . parse ( ) . unwrap ( ) ,
146
180
}
147
181
}
@@ -174,7 +208,7 @@ fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree {
174
208
impl From < TokenTree > for TokenStream {
175
209
fn from ( token : TokenTree ) -> TokenStream {
176
210
if nightly_works ( ) {
177
- TokenStream :: Compiler ( into_compiler_token ( token) . into ( ) )
211
+ TokenStream :: Compiler ( DeferredTokenStream :: new ( into_compiler_token ( token) . into ( ) ) )
178
212
} else {
179
213
TokenStream :: Fallback ( token. into ( ) )
180
214
}
@@ -184,7 +218,9 @@ impl From<TokenTree> for TokenStream {
184
218
impl iter:: FromIterator < TokenTree > for TokenStream {
185
219
fn from_iter < I : IntoIterator < Item = TokenTree > > ( trees : I ) -> Self {
186
220
if nightly_works ( ) {
187
- TokenStream :: Compiler ( trees. into_iter ( ) . map ( into_compiler_token) . collect ( ) )
221
+ TokenStream :: Compiler ( DeferredTokenStream :: new (
222
+ trees. into_iter ( ) . map ( into_compiler_token) . collect ( ) ,
223
+ ) )
188
224
} else {
189
225
TokenStream :: Fallback ( trees. into_iter ( ) . collect ( ) )
190
226
}
@@ -196,8 +232,9 @@ impl iter::FromIterator<TokenStream> for TokenStream {
196
232
let mut streams = streams. into_iter ( ) ;
197
233
match streams. next ( ) {
198
234
Some ( TokenStream :: Compiler ( mut first) ) => {
199
- first. extend ( streams. map ( |s| match s {
200
- TokenStream :: Compiler ( s) => s,
235
+ first. evaluate_now ( ) ;
236
+ first. stream . extend ( streams. map ( |s| match s {
237
+ TokenStream :: Compiler ( s) => s. into_token_stream ( ) ,
201
238
TokenStream :: Fallback ( _) => mismatch ( ) ,
202
239
} ) ) ;
203
240
TokenStream :: Compiler ( first)
@@ -218,7 +255,9 @@ impl Extend<TokenTree> for TokenStream {
218
255
fn extend < I : IntoIterator < Item = TokenTree > > ( & mut self , streams : I ) {
219
256
match self {
220
257
TokenStream :: Compiler ( tts) => {
221
- tts. extend ( streams. into_iter ( ) . map ( into_compiler_token) ) ;
258
+ // Here is the reason for DeferredTokenStream.
259
+ tts. extra
260
+ . extend ( streams. into_iter ( ) . map ( into_compiler_token) ) ;
222
261
}
223
262
TokenStream :: Fallback ( tts) => tts. extend ( streams) ,
224
263
}
@@ -229,7 +268,9 @@ impl Extend<TokenStream> for TokenStream {
229
268
fn extend < I : IntoIterator < Item = TokenStream > > ( & mut self , streams : I ) {
230
269
match self {
231
270
TokenStream :: Compiler ( tts) => {
232
- tts. extend ( streams. into_iter ( ) . map ( |stream| stream. unwrap_nightly ( ) ) ) ;
271
+ tts. evaluate_now ( ) ;
272
+ tts. stream
273
+ . extend ( streams. into_iter ( ) . map ( |stream| stream. unwrap_nightly ( ) ) ) ;
233
274
}
234
275
TokenStream :: Fallback ( tts) => {
235
276
tts. extend ( streams. into_iter ( ) . map ( |stream| stream. unwrap_stable ( ) ) ) ;
@@ -241,7 +282,7 @@ impl Extend<TokenStream> for TokenStream {
241
282
impl fmt:: Debug for TokenStream {
242
283
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
243
284
match self {
244
- TokenStream :: Compiler ( tts) => tts. fmt ( f) ,
285
+ TokenStream :: Compiler ( tts) => tts. clone ( ) . into_token_stream ( ) . fmt ( f) ,
245
286
TokenStream :: Fallback ( tts) => tts. fmt ( f) ,
246
287
}
247
288
}
@@ -280,7 +321,9 @@ impl IntoIterator for TokenStream {
280
321
281
322
fn into_iter ( self ) -> TokenTreeIter {
282
323
match self {
283
- TokenStream :: Compiler ( tts) => TokenTreeIter :: Compiler ( tts. into_iter ( ) ) ,
324
+ TokenStream :: Compiler ( tts) => {
325
+ TokenTreeIter :: Compiler ( tts. into_token_stream ( ) . into_iter ( ) )
326
+ }
284
327
TokenStream :: Fallback ( tts) => TokenTreeIter :: Fallback ( tts. into_iter ( ) ) ,
285
328
}
286
329
}
@@ -526,14 +569,14 @@ pub enum Group {
526
569
impl Group {
527
570
pub fn new ( delimiter : Delimiter , stream : TokenStream ) -> Group {
528
571
match stream {
529
- TokenStream :: Compiler ( stream ) => {
572
+ TokenStream :: Compiler ( tts ) => {
530
573
let delimiter = match delimiter {
531
574
Delimiter :: Parenthesis => proc_macro:: Delimiter :: Parenthesis ,
532
575
Delimiter :: Bracket => proc_macro:: Delimiter :: Bracket ,
533
576
Delimiter :: Brace => proc_macro:: Delimiter :: Brace ,
534
577
Delimiter :: None => proc_macro:: Delimiter :: None ,
535
578
} ;
536
- Group :: Compiler ( proc_macro:: Group :: new ( delimiter, stream ) )
579
+ Group :: Compiler ( proc_macro:: Group :: new ( delimiter, tts . into_token_stream ( ) ) )
537
580
}
538
581
TokenStream :: Fallback ( stream) => {
539
582
Group :: Fallback ( fallback:: Group :: new ( delimiter, stream) )
@@ -555,7 +598,7 @@ impl Group {
555
598
556
599
pub fn stream ( & self ) -> TokenStream {
557
600
match self {
558
- Group :: Compiler ( g) => TokenStream :: Compiler ( g. stream ( ) ) ,
601
+ Group :: Compiler ( g) => TokenStream :: Compiler ( DeferredTokenStream :: new ( g. stream ( ) ) ) ,
559
602
Group :: Fallback ( g) => TokenStream :: Fallback ( g. stream ( ) ) ,
560
603
}
561
604
}
0 commit comments