@@ -33,6 +33,7 @@ use syntax::fold::{self, Folder};
3333use syntax:: print:: { pprust} ;
3434use syntax:: print:: pprust:: PrintState ;
3535use syntax:: ptr:: P ;
36+ use syntax:: util:: ThinVec ;
3637use syntax:: util:: small_vector:: SmallVector ;
3738use syntax_pos:: { self , FileName } ;
3839
@@ -650,12 +651,17 @@ impl UserIdentifiedItem {
650651// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
651652pub struct ReplaceBodyWithLoop < ' a > {
652653 within_static_or_const : bool ,
654+ nested_blocks : Option < Vec < ast:: Block > > ,
653655 sess : & ' a Session ,
654656}
655657
656658impl < ' a > ReplaceBodyWithLoop < ' a > {
657659 pub fn new ( sess : & ' a Session ) -> ReplaceBodyWithLoop < ' a > {
658- ReplaceBodyWithLoop { within_static_or_const : false , sess }
660+ ReplaceBodyWithLoop {
661+ within_static_or_const : false ,
662+ nested_blocks : None ,
663+ sess
664+ }
659665 }
660666
661667 fn run < R , F : FnOnce ( & mut Self ) -> R > ( & mut self , is_const : bool , action : F ) -> R {
@@ -740,41 +746,81 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
740746 }
741747
742748 fn fold_block ( & mut self , b : P < ast:: Block > ) -> P < ast:: Block > {
743- fn expr_to_block ( rules : ast:: BlockCheckMode ,
749+ fn stmt_to_block ( rules : ast:: BlockCheckMode ,
744750 recovered : bool ,
745- e : Option < P < ast:: Expr > > ,
746- sess : & Session ) -> P < ast:: Block > {
747- P ( ast:: Block {
748- stmts : e. map ( |e| {
749- ast:: Stmt {
750- id : sess. next_node_id ( ) ,
751- span : e. span ,
752- node : ast:: StmtKind :: Expr ( e) ,
753- }
754- } )
755- . into_iter ( )
756- . collect ( ) ,
751+ s : Option < ast:: Stmt > ,
752+ sess : & Session ) -> ast:: Block {
753+ ast:: Block {
754+ stmts : s. into_iter ( ) . collect ( ) ,
757755 rules,
758756 id : sess. next_node_id ( ) ,
759757 span : syntax_pos:: DUMMY_SP ,
760758 recovered,
761- } )
759+ }
762760 }
763761
764- if !self . within_static_or_const {
765-
766- let empty_block = expr_to_block ( BlockCheckMode :: Default , false , None , self . sess ) ;
767- let loop_expr = P ( ast:: Expr {
768- node : ast:: ExprKind :: Loop ( empty_block, None ) ,
769- id : self . sess . next_node_id ( ) ,
762+ fn block_to_stmt ( b : ast:: Block , sess : & Session ) -> ast:: Stmt {
763+ let expr = P ( ast:: Expr {
764+ id : sess. next_node_id ( ) ,
765+ node : ast:: ExprKind :: Block ( P ( b) , None ) ,
770766 span : syntax_pos:: DUMMY_SP ,
771- attrs : ast :: ThinVec :: new ( ) ,
767+ attrs : ThinVec :: new ( ) ,
772768 } ) ;
773769
774- expr_to_block ( b. rules , b. recovered , Some ( loop_expr) , self . sess )
770+ ast:: Stmt {
771+ id : sess. next_node_id ( ) ,
772+ node : ast:: StmtKind :: Expr ( expr) ,
773+ span : syntax_pos:: DUMMY_SP ,
774+ }
775+ }
776+
777+ let empty_block = stmt_to_block ( BlockCheckMode :: Default , false , None , self . sess ) ;
778+ let loop_expr = P ( ast:: Expr {
779+ node : ast:: ExprKind :: Loop ( P ( empty_block) , None ) ,
780+ id : self . sess . next_node_id ( ) ,
781+ span : syntax_pos:: DUMMY_SP ,
782+ attrs : ast:: ThinVec :: new ( ) ,
783+ } ) ;
784+
785+ let loop_stmt = ast:: Stmt {
786+ id : self . sess . next_node_id ( ) ,
787+ span : syntax_pos:: DUMMY_SP ,
788+ node : ast:: StmtKind :: Expr ( loop_expr) ,
789+ } ;
775790
776- } else {
791+ if self . within_static_or_const {
777792 fold:: noop_fold_block ( b, self )
793+ } else {
794+ b. map ( |b| {
795+ let old_blocks = self . nested_blocks . replace ( vec ! [ ] ) ;
796+
797+ let mut stmts = b. stmts . into_iter ( )
798+ . flat_map ( |s| self . fold_stmt ( s) )
799+ . filter ( |s| s. is_item ( ) )
800+ . collect :: < Vec < ast:: Stmt > > ( ) ;
801+
802+ // we put a Some in there earlier with that replace(), so this is valid
803+ let new_blocks = self . nested_blocks . take ( ) . unwrap ( ) ;
804+ self . nested_blocks = old_blocks;
805+ stmts. extend ( new_blocks. into_iter ( ) . map ( |b| block_to_stmt ( b, & self . sess ) ) ) ;
806+
807+ let mut new_block = ast:: Block {
808+ stmts,
809+ ..b
810+ } ;
811+
812+ if let Some ( old_blocks) = self . nested_blocks . as_mut ( ) {
813+ //push our fresh block onto the cache and yield an empty block with `loop {}`
814+ old_blocks. push ( new_block) ;
815+
816+ stmt_to_block ( b. rules , b. recovered , Some ( loop_stmt) , self . sess )
817+ } else {
818+ //push `loop {}` onto the end of our fresh block and yield that
819+ new_block. stmts . push ( loop_stmt) ;
820+
821+ new_block
822+ }
823+ } )
778824 }
779825 }
780826
0 commit comments