use crate::records::constraint_generator::ConstraintGenerator;
use crate::records::scope::Scope;
use crate::records::symbol::Symbol;
use crate::type_aliases::scope_ptr_constraint_generator::ScopePtr;
use luaur_ast::records::location::Location;
impl ConstraintGenerator {
pub fn inherit_shared_refinements(
&mut self,
scope: &ScopePtr,
location: Location,
left_scope: &ScopePtr,
right_scope: &ScopePtr,
) {
let scope_raw = scope.as_ref() as *const Scope as *mut Scope;
let left_raw = left_scope.as_ref() as *const Scope as *mut Scope;
let right_raw = right_scope.as_ref() as *const Scope as *mut Scope;
unsafe {
for (left_def, left_ty) in (*left_raw).rvalue_refinements.iter() {
let left_symbol = (*self)
.dfg
.as_ref()
.and_then(|dfg| dfg.get_symbol_from_def(*left_def))
.unwrap_or_else(|| (**left_def).name.clone());
if left_symbol == Symbol::default() {
continue;
}
if scope.lookup_symbol(left_symbol.clone()).is_none() {
continue;
};
if (*left_raw).lvalue_types.find(left_def).is_none() {
let mut shadowed_by_current_def = false;
for (candidate_def, _) in (*left_raw).rvalue_refinements.iter() {
if candidate_def == left_def
|| (*left_raw).lvalue_types.find(candidate_def).is_none()
{
continue;
}
let candidate_symbol = (*self)
.dfg
.as_ref()
.and_then(|dfg| dfg.get_symbol_from_def(*candidate_def))
.unwrap_or_else(|| (**candidate_def).name.clone());
if candidate_symbol == left_symbol {
shadowed_by_current_def = true;
break;
}
}
if shadowed_by_current_def {
continue;
}
}
let mut right_match = None;
for (right_def, right_ty) in (*right_raw).rvalue_refinements.iter() {
let right_symbol = (*self)
.dfg
.as_ref()
.and_then(|dfg| dfg.get_symbol_from_def(*right_def))
.unwrap_or_else(|| (**right_def).name.clone());
if right_symbol != left_symbol {
continue;
}
if (*right_raw).lvalue_types.find(right_def).is_some() {
right_match = Some((*right_def, *right_ty));
break;
}
if *right_def == *left_def {
right_match = Some((*right_def, *right_ty));
} else if right_match.is_none() {
right_match = Some((*right_def, *right_ty));
}
}
if let Some((right_def, _)) = right_match {
if (*right_raw).lvalue_types.find(&right_def).is_none() {
for (candidate_def, candidate_ty) in (*right_raw).rvalue_refinements.iter()
{
if candidate_def == &right_def
|| (*right_raw).lvalue_types.find(candidate_def).is_none()
{
continue;
}
let candidate_symbol = (*self)
.dfg
.as_ref()
.and_then(|dfg| dfg.get_symbol_from_def(*candidate_def))
.unwrap_or_else(|| (**candidate_def).name.clone());
if candidate_symbol == left_symbol {
right_match = Some((*candidate_def, *candidate_ty));
break;
}
}
}
}
let Some((right_def, right_ty)) = right_match else {
continue;
};
let left_is_current = (*left_raw).lvalue_types.find(left_def).is_some();
let right_is_current = (*right_raw).lvalue_types.find(&right_def).is_some();
if !left_is_current && !right_is_current {
continue;
}
if !(left_is_current && self.is_shared_refinement_assignment_type(*left_ty)
|| right_is_current && self.is_shared_refinement_assignment_type(right_ty))
{
continue;
}
if (*right_raw).lvalue_types.find(&right_def).is_none() {
let mut shadowed_by_current_def = false;
for (candidate_def, _) in (*right_raw).rvalue_refinements.iter() {
if *candidate_def == right_def
|| (*right_raw).lvalue_types.find(candidate_def).is_none()
{
continue;
}
let candidate_symbol = (*self)
.dfg
.as_ref()
.and_then(|dfg| dfg.get_symbol_from_def(*candidate_def))
.unwrap_or_else(|| (**candidate_def).name.clone());
if candidate_symbol == left_symbol {
shadowed_by_current_def = true;
break;
}
}
if shadowed_by_current_def {
continue;
}
}
let ty = if *left_ty == right_ty {
*left_ty
} else {
self.make_union_scope_ptr_location_type_id_type_id(
scope_raw, location, *left_ty, right_ty,
)
};
self.update_r_value_refinements_scope_ptr_def_id_type_id(scope, *left_def, ty);
if right_def != *left_def {
self.update_r_value_refinements_scope_ptr_def_id_type_id(scope, right_def, ty);
}
}
}
}
}