rapx/analysis/core/ownedheap_analysis/
mod.rs

1pub mod default;
2
3use rustc_middle::ty::{Ty, TyKind};
4use rustc_span::def_id::DefId;
5
6use std::{
7    collections::{HashMap, HashSet},
8    env,
9    fmt::{self, Display},
10};
11
12use crate::{rap_info, utils::source::get_fn_name_byid, Analysis};
13
14#[repr(u8)]
15#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
16pub enum OwnedHeap {
17    False = 0,
18    True = 1,
19    Unknown = 2,
20}
21
22impl Default for OwnedHeap {
23    fn default() -> Self {
24        Self::Unknown
25    }
26}
27
28impl OwnedHeap {
29    pub fn is_onheap(&self) -> bool {
30        match self {
31            OwnedHeap::True => true,
32            _ => false,
33        }
34    }
35}
36
37impl Display for OwnedHeap {
38    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39        let name = match self {
40            OwnedHeap::False => "0",
41            OwnedHeap::True => "1",
42            OwnedHeap::Unknown => "2",
43        };
44        write!(f, "{}", name)
45    }
46}
47
48/// This is the type for storing the heap analysis results.
49/// The result is represented as a hashmap, where the key is `DefId` and the value contains the
50/// information of whether the type contains data on heap.
51/// Since a type could be a enumerate type, the value is represented as a vec, indicating the heap
52/// information of each variant.
53/// Also, because it may contain type parameters or generic types,
54/// the heap information is a tuple containing the information of each type parameter.
55pub type OHAResultMap = HashMap<DefId, Vec<(OwnedHeap, Vec<bool>)>>;
56pub struct OHAResultMapWrapper(pub HashMap<DefId, Vec<(OwnedHeap, Vec<bool>)>>);
57
58impl Display for OHAResultMapWrapper {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        writeln!(f, "=== Print owned heap analysis resuts ===")?;
61        for (def_id, units) in &self.0 {
62            let fn_name = get_fn_name_byid(def_id);
63            let owning = units
64                .iter()
65                .map(Self::format_heap_unit)
66                .collect::<Vec<_>>()
67                .join(", ");
68            writeln!(f, "Type: {:?}: {}", fn_name, owning)?;
69        }
70        Ok(())
71    }
72}
73
74impl OHAResultMapWrapper {
75    fn format_heap_unit((heap, bits): &(OwnedHeap, Vec<bool>)) -> String {
76        let bit_str = bits
77            .iter()
78            .map(|b| if *b { "1" } else { "0" })
79            .collect::<Vec<_>>()
80            .join(",");
81        format!("{:?}, <{}>", heap, bit_str)
82    }
83}
84/// This trait provides features for owned heap analysis, which is used to determine if a type owns
85/// memory on heap. Owned heap should be automatically released by default.
86pub trait OwnedHeapAnalysis: Analysis {
87    /// The function returns the result of owned heap analysis for all types.
88    fn get_all_items(&self) -> OHAResultMap;
89
90    /// If a type is a heap owner, the function returns Result<true>. If the specified type is
91    /// illegal, the function returns Err.
92    fn is_heapowner<'tcx>(hares: OHAResultMap, ty: Ty<'tcx>) -> Result<bool, &'static str> {
93        match ty.kind() {
94            TyKind::Adt(adtdef, ..) => {
95                let heapinfo = hares.get(&adtdef.0 .0.did).unwrap();
96                for item in heapinfo {
97                    if item.0 == OwnedHeap::True {
98                        return Ok(true);
99                    }
100                }
101                Ok(false)
102            }
103            _ => Err("The input is not an ADT"),
104        }
105    }
106
107    /// A type might be a heap owner if it is not a heap owner directly but contains type
108    /// parameters that may make the type become a heap owner after monomorphization.
109    fn maybe_heapowner<'tcx>(hares: OHAResultMap, ty: Ty<'tcx>) -> Result<bool, &'static str> {
110        match ty.kind() {
111            TyKind::Adt(adtdef, ..) => {
112                let heapinfo = hares.get(&adtdef.0 .0.did).unwrap();
113                for item in heapinfo {
114                    if item.0 == OwnedHeap::False && item.1.contains(&true) {
115                        return Ok(true);
116                    }
117                }
118                Ok(false)
119            }
120            _ => Err("The input is not an ADT"),
121        }
122    }
123}