@@ -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,18 +651,25 @@ 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 {
662
668
let old_const = mem:: replace ( & mut self . within_static_or_const , is_const) ;
669
+ let old_blocks = self . nested_blocks . take ( ) ;
663
670
let ret = action ( self ) ;
664
671
self . within_static_or_const = old_const;
672
+ self . nested_blocks = old_blocks;
665
673
ret
666
674
}
667
675
@@ -739,42 +747,88 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> {
739
747
self . run ( is_const, |s| fold:: noop_fold_impl_item ( i, s) )
740
748
}
741
749
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
+
742
754
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 ,
744
756
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 ( ) ,
757
761
rules,
758
762
id : sess. next_node_id ( ) ,
759
763
span : syntax_pos:: DUMMY_SP ,
760
764
recovered,
761
- } )
765
+ }
762
766
}
763
767
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 ) ,
770
772
span : syntax_pos:: DUMMY_SP ,
771
- attrs : ast :: ThinVec :: new ( ) ,
773
+ attrs : ThinVec :: new ( ) ,
772
774
} ) ;
773
775
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
+ }
775
782
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 {
777
798
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
+ } )
778
832
}
779
833
}
780
834
0 commit comments