luaur_analysis/methods/
constraint_generator_inherit_shared_refinements.rs1use crate::records::constraint_generator::ConstraintGenerator;
2use crate::records::scope::Scope;
3use crate::records::symbol::Symbol;
4use crate::type_aliases::scope_ptr_constraint_generator::ScopePtr;
5use luaur_ast::records::location::Location;
6
7impl ConstraintGenerator {
8 pub fn inherit_shared_refinements(
9 &mut self,
10 scope: &ScopePtr,
11 location: Location,
12 left_scope: &ScopePtr,
13 right_scope: &ScopePtr,
14 ) {
15 let scope_raw = scope.as_ref() as *const Scope as *mut Scope;
16 let left_raw = left_scope.as_ref() as *const Scope as *mut Scope;
17 let right_raw = right_scope.as_ref() as *const Scope as *mut Scope;
18
19 unsafe {
20 for (left_def, left_ty) in (*left_raw).rvalue_refinements.iter() {
21 let left_symbol = (*self)
22 .dfg
23 .as_ref()
24 .and_then(|dfg| dfg.get_symbol_from_def(*left_def))
25 .unwrap_or_else(|| (**left_def).name.clone());
26
27 if left_symbol == Symbol::default() {
28 continue;
29 }
30
31 if scope.lookup_symbol(left_symbol.clone()).is_none() {
32 continue;
33 };
34
35 if (*left_raw).lvalue_types.find(left_def).is_none() {
36 let mut shadowed_by_current_def = false;
37 for (candidate_def, _) in (*left_raw).rvalue_refinements.iter() {
38 if candidate_def == left_def
39 || (*left_raw).lvalue_types.find(candidate_def).is_none()
40 {
41 continue;
42 }
43
44 let candidate_symbol = (*self)
45 .dfg
46 .as_ref()
47 .and_then(|dfg| dfg.get_symbol_from_def(*candidate_def))
48 .unwrap_or_else(|| (**candidate_def).name.clone());
49
50 if candidate_symbol == left_symbol {
51 shadowed_by_current_def = true;
52 break;
53 }
54 }
55
56 if shadowed_by_current_def {
57 continue;
58 }
59 }
60
61 let mut right_match = None;
62 for (right_def, right_ty) in (*right_raw).rvalue_refinements.iter() {
63 let right_symbol = (*self)
64 .dfg
65 .as_ref()
66 .and_then(|dfg| dfg.get_symbol_from_def(*right_def))
67 .unwrap_or_else(|| (**right_def).name.clone());
68
69 if right_symbol != left_symbol {
70 continue;
71 }
72
73 if (*right_raw).lvalue_types.find(right_def).is_some() {
74 right_match = Some((*right_def, *right_ty));
75 break;
76 }
77
78 if *right_def == *left_def {
79 right_match = Some((*right_def, *right_ty));
80 } else if right_match.is_none() {
81 right_match = Some((*right_def, *right_ty));
82 }
83 }
84
85 if let Some((right_def, _)) = right_match {
86 if (*right_raw).lvalue_types.find(&right_def).is_none() {
87 for (candidate_def, candidate_ty) in (*right_raw).rvalue_refinements.iter()
88 {
89 if candidate_def == &right_def
90 || (*right_raw).lvalue_types.find(candidate_def).is_none()
91 {
92 continue;
93 }
94
95 let candidate_symbol = (*self)
96 .dfg
97 .as_ref()
98 .and_then(|dfg| dfg.get_symbol_from_def(*candidate_def))
99 .unwrap_or_else(|| (**candidate_def).name.clone());
100
101 if candidate_symbol == left_symbol {
102 right_match = Some((*candidate_def, *candidate_ty));
103 break;
104 }
105 }
106 }
107 }
108
109 let Some((right_def, right_ty)) = right_match else {
110 continue;
111 };
112
113 let left_is_current = (*left_raw).lvalue_types.find(left_def).is_some();
114 let right_is_current = (*right_raw).lvalue_types.find(&right_def).is_some();
115 if !left_is_current && !right_is_current {
116 continue;
117 }
118 if !(left_is_current && self.is_shared_refinement_assignment_type(*left_ty)
119 || right_is_current && self.is_shared_refinement_assignment_type(right_ty))
120 {
121 continue;
122 }
123
124 if (*right_raw).lvalue_types.find(&right_def).is_none() {
125 let mut shadowed_by_current_def = false;
126 for (candidate_def, _) in (*right_raw).rvalue_refinements.iter() {
127 if *candidate_def == right_def
128 || (*right_raw).lvalue_types.find(candidate_def).is_none()
129 {
130 continue;
131 }
132
133 let candidate_symbol = (*self)
134 .dfg
135 .as_ref()
136 .and_then(|dfg| dfg.get_symbol_from_def(*candidate_def))
137 .unwrap_or_else(|| (**candidate_def).name.clone());
138
139 if candidate_symbol == left_symbol {
140 shadowed_by_current_def = true;
141 break;
142 }
143 }
144
145 if shadowed_by_current_def {
146 continue;
147 }
148 }
149
150 let ty = if *left_ty == right_ty {
151 *left_ty
152 } else {
153 self.make_union_scope_ptr_location_type_id_type_id(
154 scope_raw, location, *left_ty, right_ty,
155 )
156 };
157
158 self.update_r_value_refinements_scope_ptr_def_id_type_id(scope, *left_def, ty);
159 if right_def != *left_def {
160 self.update_r_value_refinements_scope_ptr_def_id_type_id(scope, right_def, ty);
161 }
162 }
163 }
164 }
165}