Skip to main content

luaur_analysis/methods/
constraint_generator_inherit_shared_refinements.rs

1use 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}