|
| 1 | +use rustc_data_structures::fx::FxIndexSet; |
1 | 2 | use rustc_hir as hir;
|
2 | 3 | use rustc_hir::def_id::{DefId, LocalDefId};
|
3 | 4 | use rustc_hir::intravisit::Visitor;
|
4 | 5 | use rustc_middle::query::Providers;
|
| 6 | +use rustc_middle::span_bug; |
5 | 7 | use rustc_middle::ty::{self, TyCtxt};
|
6 | 8 |
|
7 | 9 | 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 |
13 | 54 | }
|
14 | 55 |
|
15 | 56 | struct NestedBodiesVisitor<'tcx> {
|
|
0 commit comments