@@ -615,6 +615,12 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
615
615
matches ! ( sig. header. constness, ast:: Const :: Yes ( _) )
616
616
|| matches ! ( & sig. decl. output, ast:: FnRetTy :: Ty ( ty) if ty. contains_impl_trait( ) )
617
617
}
618
+
619
+ /// Keep some `Expr`s that are ultimately assigned `DefId`s. This keeps the `HirId` parent
620
+ /// mappings correct even after this pass runs.
621
+ fn should_preserve_expr ( e : & ast:: Expr ) -> bool {
622
+ matches ! ( & e. kind, ast:: ExprKind :: Closure ( ..) | ast:: ExprKind :: Async ( ..) )
623
+ }
618
624
}
619
625
620
626
impl < ' a > MutVisitor for ReplaceBodyWithLoop < ' a , ' _ > {
@@ -644,6 +650,75 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
644
650
self . run ( true , |s| noop_visit_anon_const ( c, s) )
645
651
}
646
652
653
+ fn filter_map_expr ( & mut self , mut e : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
654
+ if self . ignore_item {
655
+ return noop_filter_map_expr ( e, self ) ;
656
+ }
657
+
658
+ if let ast:: ExprKind :: Closure ( .., decl, expr, _) = & mut e. kind {
659
+ // Replacing a closure body and removing its callsites will break inference. Give
660
+ // all closures the signature `|| -> !` to work around this.
661
+ decl. inputs = vec ! [ ] ;
662
+ if let ast:: FnRetTy :: Default ( _) = decl. output {
663
+ decl. output = ast:: FnRetTy :: Ty ( P ( ast:: Ty {
664
+ id : self . resolver . next_node_id ( ) ,
665
+ span : rustc_span:: DUMMY_SP ,
666
+ kind : ast:: TyKind :: Never ,
667
+ } ) ) ;
668
+ }
669
+
670
+ // Replace `|| expr` with `|| { expr }` so that `visit_block` gets called on the
671
+ // closure body.
672
+ if !matches ! ( expr. kind, ast:: ExprKind :: Block ( ..) ) {
673
+ let new_stmt = ast:: Stmt {
674
+ kind : ast:: StmtKind :: Expr ( expr. clone ( ) ) ,
675
+ id : self . resolver . next_node_id ( ) ,
676
+ span : expr. span ,
677
+ } ;
678
+
679
+ let new_block = ast:: Block {
680
+ stmts : vec ! [ new_stmt] ,
681
+ rules : BlockCheckMode :: Default ,
682
+ id : self . resolver . next_node_id ( ) ,
683
+ span : expr. span ,
684
+ } ;
685
+
686
+ expr. kind = ast:: ExprKind :: Block ( P ( new_block) , None ) ;
687
+ }
688
+ }
689
+
690
+ if Self :: should_preserve_expr ( & e) {
691
+ self . run ( false , |s| noop_filter_map_expr ( e, s) )
692
+ } else {
693
+ noop_filter_map_expr ( e, self )
694
+ }
695
+ }
696
+
697
+ fn flat_map_stmt ( & mut self , s : ast:: Stmt ) -> SmallVec < [ ast:: Stmt ; 1 ] > {
698
+ if self . ignore_item {
699
+ return noop_flat_map_stmt ( s, self ) ;
700
+ }
701
+
702
+ let ast:: Stmt { id, span, .. } = s;
703
+ match s. kind {
704
+ // Replace `let x = || {};` with `|| {};`
705
+ ast:: StmtKind :: Local ( mut local) if local. init . is_some ( ) => self
706
+ . filter_map_expr ( local. init . take ( ) . unwrap ( ) )
707
+ . into_iter ( )
708
+ . map ( |e| ast:: Stmt { kind : ast:: StmtKind :: Semi ( e) , id, span } )
709
+ . collect ( ) ,
710
+
711
+ // Replace `|| {}` with `|| {};`
712
+ ast:: StmtKind :: Expr ( expr) => self
713
+ . filter_map_expr ( expr)
714
+ . into_iter ( )
715
+ . map ( |e| ast:: Stmt { kind : ast:: StmtKind :: Semi ( e) , id, span } )
716
+ . collect ( ) ,
717
+
718
+ _ => noop_flat_map_stmt ( s, self ) ,
719
+ }
720
+ }
721
+
647
722
fn visit_block ( & mut self , b : & mut P < ast:: Block > ) {
648
723
fn stmt_to_block (
649
724
rules : ast:: BlockCheckMode ,
@@ -699,7 +774,13 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
699
774
for s in b. stmts {
700
775
let old_blocks = self . nested_blocks . replace ( vec ! [ ] ) ;
701
776
702
- stmts. extend ( self . flat_map_stmt ( s) . into_iter ( ) . filter ( |s| s. is_item ( ) ) ) ;
777
+ stmts. extend ( self . flat_map_stmt ( s) . into_iter ( ) . filter ( |s| {
778
+ s. is_item ( )
779
+ || matches ! (
780
+ & s. kind,
781
+ ast:: StmtKind :: Semi ( expr) if Self :: should_preserve_expr( expr)
782
+ )
783
+ } ) ) ;
703
784
704
785
// we put a Some in there earlier with that replace(), so this is valid
705
786
let new_blocks = self . nested_blocks . take ( ) . unwrap ( ) ;
0 commit comments