@@ -249,20 +249,47 @@ impl TokenStream {
249
249
0 => TokenStream :: empty ( ) ,
250
250
1 => streams. pop ( ) . unwrap ( ) ,
251
251
_ => {
252
- // rust-lang/rust#57735: pre-allocate vector to avoid
253
- // quadratic blow-up due to on-the-fly reallocations.
254
- let tree_count = streams. iter ( )
255
- . map ( |ts| match & ts. 0 { None => 0 , Some ( s) => s. len ( ) } )
252
+ // We are going to extend the first stream in `streams` with
253
+ // the elements from the subsequent streams. This requires
254
+ // using `make_mut()` on the first stream, and in practice this
255
+ // doesn't cause cloning 99.9% of the time.
256
+ //
257
+ // One very common use case is when `streams` has two elements,
258
+ // where the first stream has any number of elements within
259
+ // (often 1, but sometimes many more) and the second stream has
260
+ // a single element within.
261
+
262
+ // Determine how much the first stream will be extended.
263
+ // Needed to avoid quadratic blow up from on-the-fly
264
+ // reallocations (#57735).
265
+ let num_appends = streams. iter ( )
266
+ . skip ( 1 )
267
+ . map ( |ts| ts. len ( ) )
256
268
. sum ( ) ;
257
- let mut vec = Vec :: with_capacity ( tree_count) ;
258
269
259
- for stream in streams {
260
- match stream. 0 {
261
- None => { } ,
262
- Some ( stream2) => vec. extend ( stream2. iter ( ) . cloned ( ) ) ,
270
+ // Get the first stream. If it's `None`, create an empty
271
+ // stream.
272
+ let mut iter = streams. drain ( ) ;
273
+ let mut first_stream_lrc = match iter. next ( ) . unwrap ( ) . 0 {
274
+ Some ( first_stream_lrc) => first_stream_lrc,
275
+ None => Lrc :: new ( vec ! [ ] ) ,
276
+ } ;
277
+
278
+ // Append the elements to the first stream, after reserving
279
+ // space for them.
280
+ let first_vec_mut = Lrc :: make_mut ( & mut first_stream_lrc) ;
281
+ first_vec_mut. reserve ( num_appends) ;
282
+ for stream in iter {
283
+ if let Some ( stream) = stream. 0 {
284
+ first_vec_mut. extend ( stream. iter ( ) . cloned ( ) ) ;
263
285
}
264
286
}
265
- TokenStream :: new ( vec)
287
+
288
+ // Create the final `TokenStream`.
289
+ match first_vec_mut. len ( ) {
290
+ 0 => TokenStream ( None ) ,
291
+ _ => TokenStream ( Some ( first_stream_lrc) ) ,
292
+ }
266
293
}
267
294
}
268
295
}
@@ -363,25 +390,6 @@ impl TokenStream {
363
390
. collect ( ) )
364
391
} ) )
365
392
}
366
-
367
- fn first_tree_and_joint ( & self ) -> Option < TreeAndJoint > {
368
- self . 0 . as_ref ( ) . map ( |stream| {
369
- stream. first ( ) . unwrap ( ) . clone ( )
370
- } )
371
- }
372
-
373
- fn last_tree_if_joint ( & self ) -> Option < TokenTree > {
374
- match self . 0 {
375
- None => None ,
376
- Some ( ref stream) => {
377
- if let ( tree, Joint ) = stream. last ( ) . unwrap ( ) {
378
- Some ( tree. clone ( ) )
379
- } else {
380
- None
381
- }
382
- }
383
- }
384
- }
385
393
}
386
394
387
395
// 99.5%+ of the time we have 1 or 2 elements in this vector.
@@ -394,18 +402,49 @@ impl TokenStreamBuilder {
394
402
}
395
403
396
404
pub fn push < T : Into < TokenStream > > ( & mut self , stream : T ) {
397
- let stream = stream. into ( ) ;
398
- let last_tree_if_joint = self . 0 . last ( ) . and_then ( TokenStream :: last_tree_if_joint) ;
399
- if let Some ( TokenTree :: Token ( last_token) ) = last_tree_if_joint {
400
- if let Some ( ( TokenTree :: Token ( token) , is_joint) ) = stream. first_tree_and_joint ( ) {
401
- if let Some ( glued_tok) = last_token. glue ( & token) {
402
- let last_stream = self . 0 . pop ( ) . unwrap ( ) ;
403
- self . push_all_but_last_tree ( & last_stream) ;
404
- let glued_tt = TokenTree :: Token ( glued_tok) ;
405
- let glued_tokenstream = TokenStream :: new ( vec ! [ ( glued_tt, is_joint) ] ) ;
406
- self . 0 . push ( glued_tokenstream) ;
407
- self . push_all_but_first_tree ( & stream) ;
408
- return
405
+ let mut stream = stream. into ( ) ;
406
+
407
+ // If `self` is not empty and the last tree within the last stream is a
408
+ // token tree marked with `Joint`...
409
+ if let Some ( TokenStream ( Some ( ref mut last_stream_lrc) ) ) = self . 0 . last_mut ( ) {
410
+ if let Some ( ( TokenTree :: Token ( last_token) , Joint ) ) = last_stream_lrc. last ( ) {
411
+
412
+ // ...and `stream` is not empty and the first tree within it is
413
+ // a token tree...
414
+ if let TokenStream ( Some ( ref mut stream_lrc) ) = stream {
415
+ if let Some ( ( TokenTree :: Token ( token) , is_joint) ) = stream_lrc. first ( ) {
416
+
417
+ // ...and the two tokens can be glued together...
418
+ if let Some ( glued_tok) = last_token. glue ( & token) {
419
+
420
+ // ...then do so, by overwriting the last token
421
+ // tree in `self` and removing the first token tree
422
+ // from `stream`. This requires using `make_mut()`
423
+ // on the last stream in `self` and on `stream`,
424
+ // and in practice this doesn't cause cloning 99.9%
425
+ // of the time.
426
+
427
+ // Overwrite the last token tree with the merged
428
+ // token.
429
+ let last_vec_mut = Lrc :: make_mut ( last_stream_lrc) ;
430
+ * last_vec_mut. last_mut ( ) . unwrap ( ) =
431
+ ( TokenTree :: Token ( glued_tok) , * is_joint) ;
432
+
433
+ // Remove the first token tree from `stream`. (This
434
+ // is almost always the only tree in `stream`.)
435
+ let stream_vec_mut = Lrc :: make_mut ( stream_lrc) ;
436
+ stream_vec_mut. remove ( 0 ) ;
437
+
438
+ // Don't push `stream` if it's empty -- that could
439
+ // block subsequent token gluing, by getting
440
+ // between two token trees that should be glued
441
+ // together.
442
+ if !stream. is_empty ( ) {
443
+ self . 0 . push ( stream) ;
444
+ }
445
+ return ;
446
+ }
447
+ }
409
448
}
410
449
}
411
450
}
@@ -415,26 +454,6 @@ impl TokenStreamBuilder {
415
454
pub fn build ( self ) -> TokenStream {
416
455
TokenStream :: from_streams ( self . 0 )
417
456
}
418
-
419
- fn push_all_but_last_tree ( & mut self , stream : & TokenStream ) {
420
- if let Some ( ref streams) = stream. 0 {
421
- let len = streams. len ( ) ;
422
- match len {
423
- 1 => { }
424
- _ => self . 0 . push ( TokenStream ( Some ( Lrc :: new ( streams[ 0 .. len - 1 ] . to_vec ( ) ) ) ) ) ,
425
- }
426
- }
427
- }
428
-
429
- fn push_all_but_first_tree ( & mut self , stream : & TokenStream ) {
430
- if let Some ( ref streams) = stream. 0 {
431
- let len = streams. len ( ) ;
432
- match len {
433
- 1 => { }
434
- _ => self . 0 . push ( TokenStream ( Some ( Lrc :: new ( streams[ 1 .. len] . to_vec ( ) ) ) ) ) ,
435
- }
436
- }
437
- }
438
457
}
439
458
440
459
#[ derive( Clone ) ]
0 commit comments