@@ -33,6 +33,7 @@ use syntax::fold::{self, Folder};
33
33
use syntax:: print:: { pprust} ;
34
34
use syntax:: print:: pprust:: PrintState ;
35
35
use syntax:: ptr:: P ;
36
+ use syntax:: util:: ThinVec ;
36
37
use syntax:: util:: small_vector:: SmallVector ;
37
38
use syntax_pos:: { self , FileName } ;
38
39
@@ -650,12 +651,17 @@ impl UserIdentifiedItem {
650
651
// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401
651
652
pub struct ReplaceBodyWithLoop < ' a > {
652
653
within_static_or_const : bool ,
654
+ nested_blocks : Option < Vec < ast:: Block > > ,
653
655
sess : & ' a Session ,
654
656
}
655
657
656
658
impl < ' a > ReplaceBodyWithLoop < ' a > {
657
659
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
+ }
659
665
}
660
666
661
667
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> {
740
746
}
741
747
742
748
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 ,
744
750
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 ( ) ,
757
755
rules,
758
756
id : sess. next_node_id ( ) ,
759
757
span : syntax_pos:: DUMMY_SP ,
760
758
recovered,
761
- } )
759
+ }
762
760
}
763
761
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 ) ,
770
766
span : syntax_pos:: DUMMY_SP ,
771
- attrs : ast :: ThinVec :: new ( ) ,
767
+ attrs : ThinVec :: new ( ) ,
772
768
} ) ;
773
769
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
+ } ;
775
790
776
- } else {
791
+ if self . within_static_or_const {
777
792
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
+ } )
778
824
}
779
825
}
780
826
0 commit comments