@@ -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,18 +651,25 @@ 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 {
662668 let old_const = mem:: replace ( & mut self . within_static_or_const , is_const) ;
669+ let old_blocks = self . nested_blocks . take ( ) ;
663670 let ret = action ( self ) ;
664671 self . within_static_or_const = old_const;
672+ self . nested_blocks = old_blocks;
665673 ret
666674 }
667675
@@ -739,42 +747,88 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
739747 self . run ( is_const, |s| fold:: noop_fold_impl_item ( i, s) )
740748 }
741749
750+ fn fold_anon_const ( & mut self , c : ast:: AnonConst ) -> ast:: AnonConst {
751+ self . run ( true , |s| fold:: noop_fold_anon_const ( c, s) )
752+ }
753+
742754 fn fold_block ( & mut self , b : P < ast:: Block > ) -> P < ast:: Block > {
743- fn expr_to_block ( rules : ast:: BlockCheckMode ,
755+ fn stmt_to_block ( rules : ast:: BlockCheckMode ,
744756 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 ( ) ,
757+ s : Option < ast:: Stmt > ,
758+ sess : & Session ) -> ast:: Block {
759+ ast:: Block {
760+ stmts : s. into_iter ( ) . collect ( ) ,
757761 rules,
758762 id : sess. next_node_id ( ) ,
759763 span : syntax_pos:: DUMMY_SP ,
760764 recovered,
761- } )
765+ }
762766 }
763767
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 ( ) ,
768+ fn block_to_stmt ( b : ast:: Block , sess : & Session ) -> ast:: Stmt {
769+ let expr = P ( ast:: Expr {
770+ id : sess. next_node_id ( ) ,
771+ node : ast:: ExprKind :: Block ( P ( b) , None ) ,
770772 span : syntax_pos:: DUMMY_SP ,
771- attrs : ast :: ThinVec :: new ( ) ,
773+ attrs : ThinVec :: new ( ) ,
772774 } ) ;
773775
774- expr_to_block ( b. rules , b. recovered , Some ( loop_expr) , self . sess )
776+ ast:: Stmt {
777+ id : sess. next_node_id ( ) ,
778+ node : ast:: StmtKind :: Expr ( expr) ,
779+ span : syntax_pos:: DUMMY_SP ,
780+ }
781+ }
775782
776- } else {
783+ let empty_block = stmt_to_block ( BlockCheckMode :: Default , false , None , self . sess ) ;
784+ let loop_expr = P ( ast:: Expr {
785+ node : ast:: ExprKind :: Loop ( P ( empty_block) , None ) ,
786+ id : self . sess . next_node_id ( ) ,
787+ span : syntax_pos:: DUMMY_SP ,
788+ attrs : ast:: ThinVec :: new ( ) ,
789+ } ) ;
790+
791+ let loop_stmt = ast:: Stmt {
792+ id : self . sess . next_node_id ( ) ,
793+ span : syntax_pos:: DUMMY_SP ,
794+ node : ast:: StmtKind :: Expr ( loop_expr) ,
795+ } ;
796+
797+ if self . within_static_or_const {
777798 fold:: noop_fold_block ( b, self )
799+ } else {
800+ b. map ( |b| {
801+ let mut stmts = vec ! [ ] ;
802+ for s in b. stmts {
803+ let old_blocks = self . nested_blocks . replace ( vec ! [ ] ) ;
804+
805+ stmts. extend ( self . fold_stmt ( s) . into_iter ( ) . filter ( |s| s. is_item ( ) ) ) ;
806+
807+ // we put a Some in there earlier with that replace(), so this is valid
808+ let new_blocks = self . nested_blocks . take ( ) . unwrap ( ) ;
809+ self . nested_blocks = old_blocks;
810+ stmts. extend ( new_blocks. into_iter ( ) . map ( |b| block_to_stmt ( b, & self . sess ) ) ) ;
811+ }
812+
813+ let mut new_block = ast:: Block {
814+ stmts,
815+ ..b
816+ } ;
817+
818+ if let Some ( old_blocks) = self . nested_blocks . as_mut ( ) {
819+ //push our fresh block onto the cache and yield an empty block with `loop {}`
820+ if !new_block. stmts . is_empty ( ) {
821+ old_blocks. push ( new_block) ;
822+ }
823+
824+ stmt_to_block ( b. rules , b. recovered , Some ( loop_stmt) , self . sess )
825+ } else {
826+ //push `loop {}` onto the end of our fresh block and yield that
827+ new_block. stmts . push ( loop_stmt) ;
828+
829+ new_block
830+ }
831+ } )
778832 }
779833 }
780834
0 commit comments