@@ -21,6 +21,8 @@ use rustc_macros::HashStable_Generic;
21
21
use rustc_span:: { Span , DUMMY_SP } ;
22
22
use smallvec:: { smallvec, SmallVec } ;
23
23
24
+ use log:: debug;
25
+
24
26
use std:: { iter, mem} ;
25
27
26
28
/// When the main rust parser encounters a syntax-extension invocation, it
@@ -358,14 +360,47 @@ impl TokenStream {
358
360
// leading to some tokens being 'glued' together in one stream but not
359
361
// the other. See #68489 for more details.
360
362
fn break_tokens ( tree : TokenTree ) -> impl Iterator < Item = TokenTree > {
363
+ // In almost all cases, we should have either zero or one levels
364
+ // of 'unglueing'. However, in some unusual cases, we may need
365
+ // to iterate breaking tokens mutliple times. For example:
366
+ // '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
367
+ let mut token_trees: SmallVec < [ _ ; 2 ] > ;
361
368
if let TokenTree :: Token ( token) = & tree {
362
- if let Some ( ( first, second) ) = token. kind . break_two_token_op ( ) {
363
- return SmallVec :: from_buf ( [ TokenTree :: Token ( Token :: new ( first, DUMMY_SP ) ) , TokenTree :: Token ( Token :: new ( second, DUMMY_SP ) ) ] ) . into_iter ( )
369
+ let mut out = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
370
+ out. push ( token. clone ( ) ) ;
371
+ // Iterate to fixpoint:
372
+ // * We start off with 'out' containing our initial token, and `temp` empty
373
+ // * If we are able to break any tokens in `out`, then `out` will have
374
+ // at least one more element than 'temp', so we will try to break tokens
375
+ // again.
376
+ // * If we cannot break any tokens in 'out', we are done
377
+ loop {
378
+ let mut temp = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
379
+ let mut changed = false ;
380
+
381
+ for token in out. into_iter ( ) {
382
+ if let Some ( ( first, second) ) = token. kind . break_two_token_op ( ) {
383
+ temp. push ( Token :: new ( first, DUMMY_SP ) ) ;
384
+ temp. push ( Token :: new ( second, DUMMY_SP ) ) ;
385
+ changed = true ;
386
+ } else {
387
+ temp. push ( token) ;
388
+ }
389
+ }
390
+ out = temp;
391
+ if !changed {
392
+ break ;
393
+ }
394
+ }
395
+ token_trees = out. into_iter ( ) . map ( |t| TokenTree :: Token ( t) ) . collect ( ) ;
396
+ if token_trees. len ( ) != 1 {
397
+ debug ! ( "break_tokens: broke {:?} to {:?}" , tree, token_trees) ;
364
398
}
399
+ } else {
400
+ token_trees = SmallVec :: new ( ) ;
401
+ token_trees. push ( tree) ;
365
402
}
366
- let mut vec = SmallVec :: < [ _ ; 2 ] > :: new ( ) ;
367
- vec. push ( tree) ;
368
- vec. into_iter ( )
403
+ token_trees. into_iter ( )
369
404
}
370
405
371
406
let mut t1 = self . trees ( ) . filter ( semantic_tree) . flat_map ( break_tokens) ;
0 commit comments