Skip to content

Commit 25c39ae

Browse files
committed
Auto merge of rust-lang#141057 - compiler-errors:fast-body, r=<try>
Don't do expensive HIR walk to collect nested bodies An attempt to claw back some perf hit from the HIR-based impl of `nested_bodies_within`. r? `@ghost`
2 parents c4e05e5 + dc17ef9 commit 25c39ae

File tree

5 files changed

+61
-9
lines changed

5 files changed

+61
-9
lines changed

compiler/rustc_hir/src/def.rs

+4
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ impl DefKind {
339339
| DefKind::ExternCrate => false,
340340
}
341341
}
342+
343+
pub fn is_typeck_child(self) -> bool {
344+
matches!(self, DefKind::Closure | DefKind::InlineConst | DefKind::SyntheticCoroutineBody)
345+
}
342346
}
343347

344348
/// The resolution of a path or export.

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ pub struct ResolverGlobalCtxt {
182182
pub extern_crate_map: UnordMap<LocalDefId, CrateNum>,
183183
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
184184
pub module_children: LocalDefIdMap<Vec<ModChild>>,
185+
pub typeck_children: LocalDefIdMap<Vec<LocalDefId>>,
185186
pub glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
186187
pub main_def: Option<MainDefinition>,
187188
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,

compiler/rustc_middle/src/ty/util.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -608,10 +608,7 @@ impl<'tcx> TyCtxt<'tcx> {
608608
/// Returns `true` if `def_id` refers to a definition that does not have its own
609609
/// type-checking context, i.e. closure, coroutine or inline const.
610610
pub fn is_typeck_child(self, def_id: DefId) -> bool {
611-
matches!(
612-
self.def_kind(def_id),
613-
DefKind::Closure | DefKind::InlineConst | DefKind::SyntheticCoroutineBody
614-
)
611+
self.def_kind(def_id).is_typeck_child()
615612
}
616613

617614
/// Returns `true` if `def_id` refers to a trait (i.e., `trait Foo { ... }`).

compiler/rustc_resolve/src/lib.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,8 @@ pub struct Resolver<'ra, 'tcx> {
10731073
module_children: LocalDefIdMap<Vec<ModChild>>,
10741074
trait_map: NodeMap<Vec<TraitCandidate>>,
10751075

1076+
typeck_children: LocalDefIdMap<Vec<LocalDefId>>,
1077+
10761078
/// A map from nodes to anonymous modules.
10771079
/// Anonymous modules are pseudo-modules that are implicitly created around items
10781080
/// contained within blocks.
@@ -1347,6 +1349,11 @@ impl<'tcx> Resolver<'_, 'tcx> {
13471349
let feed = self.tcx.create_def(parent, name, def_kind, None, &mut self.disambiguator);
13481350
let def_id = feed.def_id();
13491351

1352+
if def_kind.is_typeck_child() {
1353+
let typeck_root_def_id = self.tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
1354+
self.typeck_children.entry(typeck_root_def_id).or_default().push(def_id);
1355+
}
1356+
13501357
// Create the definition.
13511358
if expn_id != ExpnId::root() {
13521359
self.expn_that_defined.insert(def_id, expn_id);
@@ -1481,6 +1488,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14811488
extra_lifetime_params_map: Default::default(),
14821489
extern_crate_map: Default::default(),
14831490
module_children: Default::default(),
1491+
typeck_children: Default::default(),
14841492
trait_map: NodeMap::default(),
14851493
underscore_disambiguator: 0,
14861494
empty_module,
@@ -1664,6 +1672,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16641672
effective_visibilities,
16651673
extern_crate_map,
16661674
module_children: self.module_children,
1675+
typeck_children: self.typeck_children,
16671676
glob_map,
16681677
maybe_unused_trait_imports,
16691678
main_def,

compiler/rustc_ty_utils/src/nested_bodies.rs

+46-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,56 @@
1+
use rustc_data_structures::fx::FxIndexSet;
12
use rustc_hir as hir;
23
use rustc_hir::def_id::{DefId, LocalDefId};
34
use rustc_hir::intravisit::Visitor;
45
use rustc_middle::query::Providers;
6+
use rustc_middle::span_bug;
57
use rustc_middle::ty::{self, TyCtxt};
68

79
fn nested_bodies_within<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx ty::List<LocalDefId> {
8-
let body = tcx.hir_body_owned_by(item);
9-
let mut collector =
10-
NestedBodiesVisitor { tcx, root_def_id: item.to_def_id(), nested_bodies: vec![] };
11-
collector.visit_body(body);
12-
tcx.mk_local_def_ids(&collector.nested_bodies)
10+
let children = if let Some(children) = tcx.resolutions(()).typeck_children.get(&item) {
11+
// We re-intern this as a `List` since `List` comparisons are cheap pointer equality.
12+
tcx.mk_local_def_ids_from_iter(
13+
children
14+
.iter()
15+
.copied()
16+
// We need to filter out the `Node::Err` bodies which were unsuccessfully
17+
// lowered in HIR lowering, like items that are contained in never pattern
18+
// match arms, which don't get lowered.
19+
.filter(|def_id| !matches!(tcx.hir_node_by_def_id(*def_id), hir::Node::Err(_))),
20+
)
21+
} else {
22+
ty::List::empty()
23+
};
24+
25+
// Double check that the list of children we're collecting here is consistent
26+
// with what we see in the HIR.
27+
if cfg!(debug_assertions) {
28+
let body = tcx.hir_body_owned_by(item);
29+
let mut collector =
30+
NestedBodiesVisitor { tcx, root_def_id: item.to_def_id(), nested_bodies: vec![] };
31+
collector.visit_body(body);
32+
33+
let mut expected = FxIndexSet::from_iter(children);
34+
for found in collector.nested_bodies {
35+
if !expected.shift_remove(&found) {
36+
span_bug!(
37+
tcx.def_span(found),
38+
"did not expect {found:#?} to be collected as a nested \
39+
body child of {item:#?}, but it appeared in the HIR",
40+
);
41+
}
42+
}
43+
44+
for expected in expected {
45+
span_bug!(
46+
tcx.def_span(expected),
47+
"expected {expected:#?} to be collected as a \
48+
nested body child of {item:#?}",
49+
);
50+
}
51+
}
52+
53+
children
1354
}
1455

1556
struct NestedBodiesVisitor<'tcx> {

0 commit comments

Comments
 (0)