rusty_cpp/analysis/
mutable_checker.rs1use crate::parser::CppAst;
2use crate::parser::ast_visitor::Class;
3use crate::parser::safety_annotations::SafetyContext;
4use crate::parser::external_annotations::ExternalAnnotations;
5
6pub fn check_mutable_fields(
12 ast: &CppAst,
13 safety_context: &SafetyContext,
14 external_annotations: Option<&ExternalAnnotations>,
15) -> Result<Vec<String>, String> {
16 use crate::debug_println;
17
18 let mut errors = Vec::new();
19
20 debug_println!("MUTABLE: Checking {} classes for mutable fields", ast.classes.len());
21
22 for class in &ast.classes {
24 debug_println!("MUTABLE: Checking class '{}' with {} members", class.name, class.members.len());
25
26 if let Some(ext_annot) = external_annotations {
29 if ext_annot.is_type_unsafe(&class.name) {
30 debug_println!("MUTABLE: Class '{}' is an unsafe_type - skipping internal analysis", class.name);
31 continue;
32 }
33 }
34
35 let class_safe = is_class_safe(class, safety_context);
37
38 debug_println!("MUTABLE: Class '{}' safe = {}", class.name, class_safe);
39
40 if !class_safe {
41 continue; }
43
44 for member in &class.members {
46 debug_println!("MUTABLE: Checking member '{}' is_mutable = {}", member.name, member.is_mutable);
47 if member.is_mutable {
48 let error = format!(
49 "{}:{} - Mutable field '{}' not allowed in safe class '{}'. \
50 Use UnsafeCell<T> and unsafe blocks for interior mutability instead.",
51 member.location.file,
52 member.location.line,
53 member.name,
54 class.name
55 );
56 errors.push(error);
57 }
58 }
59 }
60
61 debug_println!("MUTABLE: Found {} mutable field errors", errors.len());
62
63 Ok(errors)
64}
65
66fn is_class_safe(class: &Class, safety_context: &SafetyContext) -> bool {
75 use crate::parser::safety_annotations::SafetyMode;
76 use crate::debug_println;
77
78 let class_file = &class.location.file;
80
81 let class_safety = safety_context.get_class_safety_for_file(&class.name, class_file);
84 debug_println!("MUTABLE: Class '{}' from '{}' has safety mode: {:?}", class.name, class_file, class_safety);
85
86 if class_safety == SafetyMode::Safe {
89 debug_println!("MUTABLE: Class '{}' is marked @safe - checking for mutable fields", class.name);
90 return true;
91 }
92
93 debug_println!("MUTABLE: Class '{}' is @unsafe - mutable fields allowed", class.name);
94 false
95}