rapx/analysis/heap_ownership/
mod.rs1pub 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::{Analysis, utils::source::get_fn_name_byid};
13
14#[repr(u8)]
15#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
16pub enum HeapOwnership {
17 False = 0,
18 True = 1,
19 Unknown = 2,
20}
21
22impl Default for HeapOwnership {
23 fn default() -> Self {
24 Self::Unknown
25 }
26}
27
28impl HeapOwnership {
29 pub fn is_onheap(&self) -> bool {
30 matches!(self, HeapOwnership::True)
31 }
32}
33
34impl Display for HeapOwnership {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 let name = match self {
37 HeapOwnership::False => "0",
38 HeapOwnership::True => "1",
39 HeapOwnership::Unknown => "2",
40 };
41 write!(f, "{}", name)
42 }
43}
44
45pub type HeapOwnershipResultMap = HashMap<DefId, Vec<(HeapOwnership, Vec<bool>)>>;
53pub struct HeapOwnershipResultMapWrapper(pub HashMap<DefId, Vec<(HeapOwnership, Vec<bool>)>>);
54
55impl Display for HeapOwnershipResultMapWrapper {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 writeln!(f, "=== Print heap ownership analysis results ===")?;
58 for (def_id, units) in &self.0 {
59 let fn_name = get_fn_name_byid(def_id);
60 let owning = units
61 .iter()
62 .map(Self::format_heap_unit)
63 .collect::<Vec<_>>()
64 .join(", ");
65 writeln!(f, "Type: {:?}: {}", fn_name, owning)?;
66 }
67 Ok(())
68 }
69}
70
71impl HeapOwnershipResultMapWrapper {
72 fn format_heap_unit((heap, bits): &(HeapOwnership, Vec<bool>)) -> String {
73 let bit_str = bits
74 .iter()
75 .map(|b| if *b { "1" } else { "0" })
76 .collect::<Vec<_>>()
77 .join(",");
78 format!("{:?}, <{}>", heap, bit_str)
79 }
80}
81pub trait HeapOwnershipAnalysis: Analysis {
84 fn get_all_items(&self) -> HeapOwnershipResultMap;
86
87 fn is_heapowner<'tcx>(
90 hares: HeapOwnershipResultMap,
91 ty: Ty<'tcx>,
92 ) -> 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 == HeapOwnership::True {
98 return Ok(true);
99 }
100 }
101 Ok(false)
102 }
103 _ => Err("The input is not an ADT"),
104 }
105 }
106
107 fn maybe_heapowner<'tcx>(
110 hares: HeapOwnershipResultMap,
111 ty: Ty<'tcx>,
112 ) -> Result<bool, &'static str> {
113 match ty.kind() {
114 TyKind::Adt(adtdef, ..) => {
115 let heapinfo = hares.get(&adtdef.0.0.did).unwrap();
116 for item in heapinfo {
117 if item.0 == HeapOwnership::False && item.1.contains(&true) {
118 return Ok(true);
119 }
120 }
121 Ok(false)
122 }
123 _ => Err("The input is not an ADT"),
124 }
125 }
126}