rapx/analysis/points_to/
builder.rs1use rustc_hir::def_id::DefId;
2use rustc_middle::ty::{self, Ty, TyCtxt, TypingEnv};
3
4use crate::analysis::alias::default::types::{is_not_drop, kind};
5
6use super::graph::PtsGraph;
7use super::slot::Slot;
8
9const MAX_FIELD_DEPTH: usize = 5;
10const MAX_DEREF_DEPTH: usize = 3;
11
12pub fn from_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> PtsGraph {
15 let body = tcx.optimized_mir(def_id);
16 let mut graph = PtsGraph::new();
17 let ty_env = TypingEnv::post_analysis(tcx, def_id);
18
19 for (local, local_decl) in body.local_decls.iter_enumerated() {
20 let ty = local_decl.ty;
21 let need_drop = ty.needs_drop(tcx, ty_env);
22 let may_drop = !is_not_drop(tcx, ty);
23
24 let slot = Slot::new(local.as_usize());
25 let slot_idx = graph.ensure_slot(slot.clone(), may_drop, need_drop);
26 graph.set_slot_kind(slot_idx, kind(ty));
27
28 register_field_slots(tcx, ty, &slot, slot_idx, &mut graph, 0, 0, ty_env);
29 }
30
31 graph
32}
33
34fn register_field_slots<'tcx>(
37 tcx: TyCtxt<'tcx>,
38 ty: Ty<'tcx>,
39 base_slot: &Slot,
40 _base_idx: usize,
41 graph: &mut PtsGraph,
42 field_depth: usize,
43 deref_depth: usize,
44 ty_env: TypingEnv<'tcx>,
45) {
46 if field_depth >= MAX_FIELD_DEPTH || deref_depth >= MAX_DEREF_DEPTH {
47 return;
48 }
49
50 match ty.kind() {
51 ty::Ref(_, inner_ty, _) | ty::RawPtr(inner_ty, _) => {
52 register_field_slots(
53 tcx, *inner_ty, base_slot, _base_idx, graph,
54 field_depth, deref_depth + 1, ty_env,
55 );
56 }
57 ty::Adt(adt_def, substs) => {
58 for (field_idx, field) in adt_def.all_fields().enumerate() {
59 let field_slot = base_slot.project(field_idx);
60 #[cfg(not(rapx_ge_99))]
61 let field_ty = field.ty(tcx, substs);
62 #[cfg(rapx_ge_99)]
63 let field_ty = field.ty(tcx, substs).skip_norm_wip();
64 let need_drop = field_ty.needs_drop(tcx, ty_env);
65 let may_drop = if deref_depth > 0 {
66 true
67 } else {
68 !is_not_drop(tcx, field_ty)
69 };
70 let field_idx_global =
71 graph.ensure_slot(field_slot.clone(), may_drop, need_drop);
72 graph.set_slot_kind(field_idx_global, kind(field_ty));
73 register_field_slots(
74 tcx, field_ty, &field_slot, field_idx_global, graph,
75 field_depth + 1, deref_depth, ty_env,
76 );
77 }
78 }
79 ty::Tuple(fields) => {
80 for (field_idx, field_ty) in fields.iter().enumerate() {
81 let field_slot = base_slot.project(field_idx);
82 let may_drop = if deref_depth > 0 {
83 true
84 } else {
85 !is_not_drop(tcx, field_ty)
86 };
87 let need_drop = field_ty.needs_drop(tcx, ty_env);
88 let field_idx_global =
89 graph.ensure_slot(field_slot.clone(), may_drop, need_drop);
90 graph.set_slot_kind(field_idx_global, kind(field_ty));
91 register_field_slots(
92 tcx, field_ty, &field_slot, field_idx_global, graph,
93 field_depth + 1, deref_depth, ty_env,
94 );
95 }
96 }
97 _ => {}
98 }
99}