@@ -719,6 +719,19 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
719719 }
720720 }
721721
722+ // We need to keep certain Expr nodes because they can contain
723+ // exported macros. If we were to remove a parent of a MacroDef
724+ // node, we would end up with in a case where the macro is properly
725+ // lowered but not its parent, causing some surprising bug while
726+ // trying to access the parent HirId. See issue #71820.
727+ fn expr_to_keep ( e : & ast:: Expr ) -> bool {
728+ match e. kind {
729+ ast:: ExprKind :: Closure ( ..) => true ,
730+ ast:: ExprKind :: Async ( ..) => true ,
731+ _ => false ,
732+ }
733+ }
734+
722735 let empty_block = stmt_to_block ( BlockCheckMode :: Default , None , self . resolver ) ;
723736 let loop_expr = P ( ast:: Expr {
724737 kind : ast:: ExprKind :: Loop ( P ( empty_block) , None ) ,
@@ -741,7 +754,11 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
741754 for s in b. stmts {
742755 let old_blocks = self . nested_blocks . replace ( vec ! [ ] ) ;
743756
744- stmts. extend ( self . flat_map_stmt ( s) . into_iter ( ) . filter ( |s| s. is_item ( ) ) ) ;
757+ stmts. extend (
758+ self . flat_map_stmt ( s) . into_iter ( ) . filter ( |s| {
759+ s. is_item ( ) || s. as_expr ( ) . map_or ( false , |e| expr_to_keep ( e) )
760+ } ) ,
761+ ) ;
745762
746763 // we put a Some in there earlier with that replace(), so this is valid
747764 let new_blocks = self . nested_blocks . take ( ) . unwrap ( ) ;
0 commit comments