@@ -719,6 +719,19 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
719
719
}
720
720
}
721
721
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
+
722
735
let empty_block = stmt_to_block ( BlockCheckMode :: Default , None , self . resolver ) ;
723
736
let loop_expr = P ( ast:: Expr {
724
737
kind : ast:: ExprKind :: Loop ( P ( empty_block) , None ) ,
@@ -741,7 +754,11 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
741
754
for s in b. stmts {
742
755
let old_blocks = self . nested_blocks . replace ( vec ! [ ] ) ;
743
756
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
+ ) ;
745
762
746
763
// we put a Some in there earlier with that replace(), so this is valid
747
764
let new_blocks = self . nested_blocks . take ( ) . unwrap ( ) ;
0 commit comments