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
9use crate::limit::{MAX_DEREF_DEPTH, MAX_FIELD_DEPTH};
10
11pub fn from_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> PtsGraph {
14 let body = tcx.optimized_mir(def_id);
15 let mut graph = PtsGraph::new();
16 let ty_env = TypingEnv::post_analysis(tcx, def_id);
17
18 for (local, local_decl) in body.local_decls.iter_enumerated() {
19 let ty = local_decl.ty;
20 let need_drop = ty.needs_drop(tcx, ty_env);
21 let may_drop = !is_not_drop(tcx, ty);
22
23 let slot = Slot::new(local.as_usize());
24 let slot_idx = graph.ensure_slot(slot.clone(), may_drop, need_drop);
25 graph.set_slot_kind(slot_idx, kind(ty));
26
27 register_field_slots(tcx, ty, &slot, &mut graph, 0, 0, ty_env);
28 }
29
30 graph
31}
32
33fn register_field_slots<'tcx>(
36 tcx: TyCtxt<'tcx>,
37 ty: Ty<'tcx>,
38 base_slot: &Slot,
39 graph: &mut PtsGraph,
40 field_depth: usize,
41 deref_depth: usize,
42 ty_env: TypingEnv<'tcx>,
43) {
44 if field_depth >= MAX_FIELD_DEPTH || deref_depth >= MAX_DEREF_DEPTH {
45 return;
46 }
47
48 match ty.kind() {
49 ty::Ref(_, inner_ty, _) | ty::RawPtr(inner_ty, _) => {
50 register_field_slots(
51 tcx,
52 *inner_ty,
53 base_slot,
54 graph,
55 field_depth,
56 deref_depth + 1,
57 ty_env,
58 );
59 }
60 ty::Adt(adt_def, substs) => {
61 for (field_idx, field) in adt_def.all_fields().enumerate() {
62 let field_slot = base_slot.project(field_idx);
63 let field_ty = crate::helpers::mir_utils::field_ty(tcx, field, substs);
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 = graph.ensure_slot(field_slot.clone(), may_drop, need_drop);
71 graph.set_slot_kind(field_idx_global, kind(field_ty));
72 register_field_slots(
73 tcx,
74 field_ty,
75 &field_slot,
76 graph,
77 field_depth + 1,
78 deref_depth,
79 ty_env,
80 );
81 }
82 }
83 ty::Tuple(fields) => {
84 for (field_idx, field_ty) in fields.iter().enumerate() {
85 let field_slot = base_slot.project(field_idx);
86 let may_drop = if deref_depth > 0 {
87 true
88 } else {
89 !is_not_drop(tcx, field_ty)
90 };
91 let need_drop = field_ty.needs_drop(tcx, ty_env);
92 let field_idx_global = graph.ensure_slot(field_slot.clone(), may_drop, need_drop);
93 graph.set_slot_kind(field_idx_global, kind(field_ty));
94 register_field_slots(
95 tcx,
96 field_ty,
97 &field_slot,
98 graph,
99 field_depth + 1,
100 deref_depth,
101 ty_env,
102 );
103 }
104 }
105 _ => {}
106 }
107}