Skip to content

Commit 1941a43

Browse files
committed
Do not remove closures during ReplaceBodyWithLoop pass
Fixes rust-lang#71820
1 parent 34d6b44 commit 1941a43

File tree

5 files changed

+41
-6
lines changed

5 files changed

+41
-6
lines changed

src/librustc_ast/ast.rs

+9
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,15 @@ impl Stmt {
899899
_ => false,
900900
}
901901
}
902+
903+
pub fn as_expr(&self) -> Option<&Expr> {
904+
match self.kind {
905+
StmtKind::Local(ref l) => l.init.as_ref().map(|e| &**e),
906+
StmtKind::Expr(ref e) => Some(e),
907+
StmtKind::Semi(ref e) => Some(e),
908+
_ => None,
909+
}
910+
}
902911
}
903912

904913
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]

src/librustc_interface/util.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -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();

src/librustc_privacy/lib.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -944,11 +944,8 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
944944
let macro_module_def_id =
945945
ty::DefIdTree::parent(self.tcx, self.tcx.hir().local_def_id(md.hir_id).to_def_id())
946946
.unwrap();
947-
// FIXME(#71104) Should really be using just `as_local_hir_id` but
948-
// some `DefId` do not seem to have a corresponding HirId.
949-
let hir_id = macro_module_def_id
950-
.as_local()
951-
.and_then(|def_id| self.tcx.hir().opt_local_def_id_to_hir_id(def_id));
947+
let hir_id =
948+
macro_module_def_id.as_local().map(|def_id| self.tcx.hir().as_local_hir_id(def_id));
952949
let mut module_id = match hir_id {
953950
Some(module_id) if self.tcx.hir().is_hir_id_module(module_id) => module_id,
954951
// `module_id` doesn't correspond to a `mod`, return early (#63164, #65252).
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Regression issue for rustdoc ICE encountered in PR #72088.
2+
// edition:2018
3+
#![feature(decl_macro)]
4+
5+
fn main() {
6+
async {
7+
macro m() {}
8+
};
9+
}

src/test/rustdoc/macro-in-closure.rs

+3
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@ fn main() {
66
|| {
77
macro m() {}
88
};
9+
let _ = || {
10+
macro n() {}
11+
};
912
}

0 commit comments

Comments
 (0)