@@ -615,6 +615,12 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> {
615615        matches ! ( sig. header. constness,  ast:: Const :: Yes ( _) ) 
616616            || matches ! ( & sig. decl. output,  ast:: FnRetTy :: Ty ( ty)  if  ty. contains_impl_trait( ) ) 
617617    } 
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+     } 
618624} 
619625
620626impl < ' a >  MutVisitor  for  ReplaceBodyWithLoop < ' a ,  ' _ >  { 
@@ -644,6 +650,75 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
644650        self . run ( true ,  |s| noop_visit_anon_const ( c,  s) ) 
645651    } 
646652
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+ 
647722    fn  visit_block ( & mut  self ,  b :  & mut  P < ast:: Block > )  { 
648723        fn  stmt_to_block ( 
649724            rules :  ast:: BlockCheckMode , 
@@ -699,7 +774,13 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
699774            for  s in  b. stmts  { 
700775                let  old_blocks = self . nested_blocks . replace ( vec ! [ ] ) ; 
701776
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+                 } ) ) ; 
703784
704785                // we put a Some in there earlier with that replace(), so this is valid 
705786                let  new_blocks = self . nested_blocks . take ( ) . unwrap ( ) ; 
0 commit comments