about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils/src/nested_bodies.rs
blob: 7c74d8eb635185c72e8bd49359d05626565405c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt};

fn nested_bodies_within<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx ty::List<LocalDefId> {
    let body = tcx.hir_body_owned_by(item);
    let mut collector =
        NestedBodiesVisitor { tcx, root_def_id: item.to_def_id(), nested_bodies: vec![] };
    collector.visit_body(body);
    tcx.mk_local_def_ids(&collector.nested_bodies)
}

struct NestedBodiesVisitor<'tcx> {
    tcx: TyCtxt<'tcx>,
    root_def_id: DefId,
    nested_bodies: Vec<LocalDefId>,
}

impl<'tcx> Visitor<'tcx> for NestedBodiesVisitor<'tcx> {
    fn visit_nested_body(&mut self, id: hir::BodyId) {
        let body_def_id = self.tcx.hir_body_owner_def_id(id);
        if self.tcx.typeck_root_def_id(body_def_id.to_def_id()) == self.root_def_id {
            self.nested_bodies.push(body_def_id);
            let body = self.tcx.hir_body(id);
            self.visit_body(body);
        }
    }
}

pub(super) fn provide(providers: &mut Providers) {
    *providers = Providers { nested_bodies_within, ..*providers };
}