rapx/check/safedrop/
graph.rs

1use super::{bug_records::*, drop::*};
2use crate::analysis::{
3    alias_analysis::default::graph::AliasGraph, ownedheap_analysis::OHAResultMap,
4    path_analysis::graph::PathGraph,
5};
6use rustc_middle::ty::TyCtxt;
7use rustc_span::def_id::DefId;
8use std::{fmt, vec::Vec};
9
10/// We represent each target function with the `SafeDropGraph` struct and then perform analysis
11/// based on the struct.
12pub struct SafeDropGraph<'tcx> {
13    pub alias_graph: AliasGraph<'tcx>,
14    pub bug_records: BugRecords,
15    pub drop_record: Vec<DropRecord>,
16    // analysis of heap item
17    pub adt_owner: OHAResultMap,
18}
19
20impl<'tcx> SafeDropGraph<'tcx> {
21    pub fn new(tcx: TyCtxt<'tcx>, def_id: DefId, adt_owner: OHAResultMap) -> Self {
22        let alias_graph = AliasGraph::new(tcx, def_id);
23        let mut drop_record = Vec::<DropRecord>::new();
24        for v in &alias_graph.values {
25            drop_record.push(DropRecord::false_record(v.index));
26        }
27
28        SafeDropGraph {
29            alias_graph,
30            bug_records: BugRecords::new(),
31            drop_record,
32            adt_owner,
33        }
34    }
35
36    pub fn from_path_graph(
37        tcx: TyCtxt<'tcx>,
38        def_id: DefId,
39        path_graph: PathGraph<'tcx>,
40        adt_owner: OHAResultMap,
41    ) -> Self {
42        let alias_graph = AliasGraph::from_path_graph(tcx, def_id, path_graph);
43        let mut drop_record = Vec::<DropRecord>::new();
44        for v in &alias_graph.values {
45            drop_record.push(DropRecord::false_record(v.index));
46        }
47
48        SafeDropGraph {
49            alias_graph,
50            bug_records: BugRecords::new(),
51            drop_record,
52            adt_owner,
53        }
54    }
55
56    /// Ensure `drop_record` matches the current length of `alias_graph.values`.
57    /// Call this after any alias operation that may create new value nodes
58    /// (`projection`, `sync_field_alias`, `sync_father_alias`, `handle_fn_alias`, etc.).
59    pub fn sync_drop_record(&mut self) {
60        while self.drop_record.len() < self.alias_graph.values.len() {
61            let new_idx = self.drop_record.len();
62            let father = self.alias_graph.values[new_idx].father.clone();
63            self.drop_record.push(if let Some(fi) = father {
64                DropRecord::from(new_idx, &self.drop_record[fi.father_value_id])
65            } else {
66                DropRecord::false_record(new_idx)
67            });
68        }
69    }
70}
71
72impl<'tcx> std::fmt::Display for SafeDropGraph<'tcx> {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        writeln!(f, "SafeDropGraph {{")?;
75        writeln!(f, "  AliasGraph: {}", self.alias_graph)?;
76        write!(f, "}}")
77    }
78}