rusty_cpp/analysis/
this_tracking.rs1use std::collections::{HashMap, HashSet};
2use crate::ir::BorrowKind;
3use crate::parser::MethodQualifier;
4
5#[derive(Debug, Clone)]
12pub struct ThisPointerTracker {
13 method_qualifier: Option<MethodQualifier>,
15
16 moved_fields: HashSet<String>,
18
19 borrowed_fields: HashMap<String, BorrowKind>,
21}
22
23impl ThisPointerTracker {
24 pub fn new(method_qualifier: Option<MethodQualifier>) -> Self {
26 Self {
27 method_qualifier,
28 moved_fields: HashSet::new(),
29 borrowed_fields: HashMap::new(),
30 }
31 }
32
33 pub fn can_read_member(&self, field: &str) -> Result<(), String> {
39 if self.moved_fields.contains(field) {
40 return Err(format!("Cannot read field '{}': field has been moved", field));
41 }
42 Ok(())
43 }
44
45 pub fn can_modify_member(&self, field: &str) -> Result<(), String> {
54 if self.moved_fields.contains(field) {
55 return Err(format!("Cannot modify field '{}': field has been moved", field));
56 }
57
58 if let Some(MethodQualifier::Const) = self.method_qualifier {
60 return Err(format!(
61 "Cannot modify field '{}' in const method (use non-const method for &mut self semantics)",
62 field
63 ));
64 }
65
66 if let Some(BorrowKind::Immutable) = self.borrowed_fields.get(field) {
68 return Err(format!(
69 "Cannot modify field '{}': field is currently borrowed immutably",
70 field
71 ));
72 }
73
74 Ok(())
75 }
76
77 pub fn can_move_member(&self, field: &str) -> Result<(), String> {
86 if self.moved_fields.contains(field) {
87 return Err(format!("Cannot move field '{}': field has already been moved", field));
88 }
89
90 if self.borrowed_fields.contains_key(field) {
92 return Err(format!(
93 "Cannot move field '{}': field is currently borrowed",
94 field
95 ));
96 }
97
98 match self.method_qualifier {
100 Some(MethodQualifier::Const) => {
101 Err(format!(
102 "Cannot move field '{}' from const method (requires && method for self ownership)",
103 field
104 ))
105 }
106 Some(MethodQualifier::NonConst) => {
107 Err(format!(
108 "Cannot move field '{}' from &mut self method (use && qualified method for self ownership)",
109 field
110 ))
111 }
112 Some(MethodQualifier::RvalueRef) => {
113 Ok(())
115 }
116 None => {
117 Ok(())
119 }
120 }
121 }
122
123 pub fn can_borrow_member(&self, field: &str, kind: BorrowKind) -> Result<(), String> {
132 if self.moved_fields.contains(field) {
133 return Err(format!("Cannot borrow field '{}': field has been moved", field));
134 }
135
136 if let Some(MethodQualifier::Const) = self.method_qualifier {
138 if matches!(kind, BorrowKind::Mutable) {
139 return Err(format!(
140 "Cannot create mutable borrow of field '{}' in const method",
141 field
142 ));
143 }
144 }
145
146 if let Some(existing_kind) = self.borrowed_fields.get(field) {
148 match (existing_kind, kind) {
149 (BorrowKind::Mutable, _) => {
150 return Err(format!(
151 "Cannot borrow field '{}': already borrowed mutably",
152 field
153 ));
154 }
155 (BorrowKind::Immutable, BorrowKind::Mutable) => {
156 return Err(format!(
157 "Cannot borrow field '{}' mutably: already borrowed immutably",
158 field
159 ));
160 }
161 (BorrowKind::Immutable, BorrowKind::Immutable) => {
162 Ok(())
164 }
165 }
166 } else {
167 Ok(())
168 }
169 }
170
171 pub fn mark_field_moved(&mut self, field: String) {
173 self.moved_fields.insert(field.clone());
174 self.borrowed_fields.remove(&field); }
176
177 pub fn mark_field_borrowed(&mut self, field: String, kind: BorrowKind) {
179 self.borrowed_fields.insert(field, kind);
180 }
181
182 pub fn clear_field_borrow(&mut self, field: &str) {
184 self.borrowed_fields.remove(field);
185 }
186
187 pub fn method_qualifier(&self) -> Option<&MethodQualifier> {
189 self.method_qualifier.as_ref()
190 }
191
192 pub fn is_field_moved(&self, field: &str) -> bool {
194 self.moved_fields.contains(field)
195 }
196
197 pub fn is_field_borrowed(&self, field: &str) -> bool {
199 self.borrowed_fields.contains_key(field)
200 }
201}