use crate::enums::polarity::Polarity;
use crate::functions::flatten_type_pack_alt_b::flatten;
use crate::functions::fresh_type::fresh_type;
use crate::functions::is_blocked_unifier_alt_c::is_blocked_txn_log_type_pack_id;
use crate::functions::is_optional::is_optional;
use crate::functions::size_type_pack::size;
use crate::records::count_mismatch::{CountMismatch, CountMismatchContext};
use crate::records::free_type_pack::FreeTypePack;
use crate::records::type_pack::TypePack;
use crate::records::type_pack_mismatch::TypePackMismatch;
use crate::records::type_pack_var::TypePackVar;
use crate::records::unifier::Unifier;
use crate::records::variadic_type_pack::VariadicTypePack;
use crate::records::weird_iter::WeirdIter;
use crate::records::widen::Widen;
use crate::type_aliases::error_type_pack::ErrorTypePack;
use crate::type_aliases::type_error_data::TypeErrorData;
use crate::type_aliases::type_pack_id::TypePackId;
use crate::type_aliases::type_pack_variant::TypePackVariant;
use alloc::string::String;
impl Unifier {
pub fn try_unify_type_pack_id_type_pack_id_bool(
&mut self,
mut sub_tp: TypePackId,
mut super_tp: TypePackId,
is_function_call: bool,
) {
unsafe {
(*self.shared_state).counters.iteration_count += 1;
if (*self.shared_state).counters.iteration_limit > 0
&& (*self.shared_state).counters.iteration_limit
< (*self.shared_state).counters.iteration_count
{
self.report_error_location_type_error_data(
self.location,
TypeErrorData::UnificationTooComplex(
crate::records::unification_too_complex::UnificationTooComplex::default(),
),
);
return;
}
}
super_tp = self.log.follow_type_pack_id(super_tp);
sub_tp = self.log.follow_type_pack_id(sub_tp);
if self.reflexive_equal_type_pack_id(super_tp, sub_tp, 32) {
return;
}
loop {
let tp = self.log.txn_log_get_mutable::<TypePack, TypePackId>(sub_tp);
if tp.is_null() {
break;
}
if unsafe { (*tp).head.is_empty() && (*tp).tail.is_some() } {
sub_tp = self.log.follow_type_pack_id(unsafe { (*tp).tail.unwrap() });
} else {
break;
}
}
loop {
let tp = self
.log
.txn_log_get_mutable::<TypePack, TypePackId>(super_tp);
if tp.is_null() {
break;
}
if unsafe { (*tp).head.is_empty() && (*tp).tail.is_some() } {
super_tp = self.log.follow_type_pack_id(unsafe { (*tp).tail.unwrap() });
} else {
break;
}
}
if super_tp == sub_tp {
return;
}
if self
.log
.have_seen_type_pack_id_type_pack_id(super_tp, sub_tp)
{
return;
}
let sub_blocked = is_blocked_txn_log_type_pack_id(&self.log, sub_tp);
let super_blocked = is_blocked_txn_log_type_pack_id(&self.log, super_tp);
if sub_blocked && super_blocked {
self.blocked_type_packs.push(sub_tp);
self.blocked_type_packs.push(super_tp);
} else if sub_blocked {
self.blocked_type_packs.push(sub_tp);
} else if super_blocked {
self.blocked_type_packs.push(super_tp);
}
if !self
.log
.txn_log_get_mutable::<FreeTypePack, TypePackId>(super_tp)
.is_null()
{
if !self.occurs_check_type_pack_id_type_pack_id_bool(super_tp, sub_tp, true) {
let mut widen = Widen::widen_widen(self.types, self.builtin_types);
let widened = widen.operator_call(sub_tp);
let bound = TypePackVar {
ty: TypePackVariant::Bound(widened),
persistent: false,
owningArena: core::ptr::null_mut(),
};
self.log.replace_type_pack_id_type_pack_var(super_tp, bound);
}
} else if !self
.log
.txn_log_get_mutable::<FreeTypePack, TypePackId>(sub_tp)
.is_null()
{
if !self.occurs_check_type_pack_id_type_pack_id_bool(sub_tp, super_tp, false) {
let bound = TypePackVar {
ty: TypePackVariant::Bound(super_tp),
persistent: false,
owningArena: core::ptr::null_mut(),
};
self.log.replace_type_pack_id_type_pack_var(sub_tp, bound);
}
} else if !self
.log
.txn_log_get_mutable::<ErrorTypePack, TypePackId>(super_tp)
.is_null()
{
self.try_unify_with_any_type_pack_id_type_pack_id(sub_tp, super_tp);
} else if !self
.log
.txn_log_get_mutable::<ErrorTypePack, TypePackId>(sub_tp)
.is_null()
{
self.try_unify_with_any_type_pack_id_type_pack_id(super_tp, sub_tp);
} else if !self
.log
.txn_log_get_mutable::<VariadicTypePack, TypePackId>(super_tp)
.is_null()
{
self.unifier_try_unify_variadics(sub_tp, super_tp, false, 0);
} else if !self
.log
.txn_log_get_mutable::<VariadicTypePack, TypePackId>(sub_tp)
.is_null()
{
self.unifier_try_unify_variadics(super_tp, sub_tp, true, 0);
} else if !self
.log
.txn_log_get_mutable::<TypePack, TypePackId>(super_tp)
.is_null()
&& !self
.log
.txn_log_get_mutable::<TypePack, TypePackId>(sub_tp)
.is_null()
{
let super_tpv = self
.log
.txn_log_get_mutable::<TypePack, TypePackId>(super_tp);
let sub_tpv = self.log.txn_log_get_mutable::<TypePack, TypePackId>(sub_tp);
let (super_types, super_tail) = flatten(super_tp, &self.log);
let (sub_types, sub_tail) = flatten(sub_tp, &self.log);
let no_infinite_growth = (super_types.len() != sub_types.len())
&& super_tail.map_or(false, |t| {
!self
.log
.txn_log_get_mutable::<FreeTypePack, TypePackId>(t)
.is_null()
})
&& sub_tail.map_or(false, |t| {
!self
.log
.txn_log_get_mutable::<FreeTypePack, TypePackId>(t)
.is_null()
});
let mut super_iter = WeirdIter {
pack_id: super_tp,
log: &mut self.log as *mut _,
pack: core::ptr::null_mut(),
index: 0,
growing: false,
level: crate::records::type_level::TypeLevel::default(),
scope: core::ptr::null_mut(),
};
super_iter.weird_iter_type_pack_id_txn_log(super_tp, unsafe { &mut *(self.log_ptr()) });
let mut sub_iter = WeirdIter {
pack_id: sub_tp,
log: &mut self.log as *mut _,
pack: core::ptr::null_mut(),
index: 0,
growing: false,
level: crate::records::type_level::TypeLevel::default(),
scope: core::ptr::null_mut(),
};
sub_iter.weird_iter_type_pack_id_txn_log(sub_tp, unsafe { &mut *(self.log_ptr()) });
super_iter.scope = self.scope;
sub_iter.scope = self.scope;
let empty_tp = unsafe {
(*self.types).add_type_pack_t(TypePack {
head: alloc::vec::Vec::new(),
tail: None,
})
};
let mut loop_count = 0;
loop {
if luaur_common::FInt::LuauTypeInferTypePackLoopLimit.get() > 0
&& loop_count >= luaur_common::FInt::LuauTypeInferTypePackLoopLimit.get()
{
self.ice_string("Detected possibly infinite TypePack growth");
}
loop_count += 1;
if super_iter.weird_iter_good() && sub_iter.growing {
let ft = self.mk_fresh_for_iter(sub_iter.scope);
sub_iter.weird_iter_push_type(ft);
}
if sub_iter.weird_iter_good() && super_iter.growing {
let ft = self.mk_fresh_for_iter(super_iter.scope);
super_iter.weird_iter_push_type(ft);
}
if super_iter.weird_iter_good() && sub_iter.weird_iter_good() {
let s = *sub_iter.weird_iter_operator_deref();
let sup = *super_iter.weird_iter_operator_deref();
self.try_unify_type_id_type_id_bool_bool_literal_properties(
s, sup, false, false, None,
);
if !self.errors.is_empty() && self.first_pack_error_pos.is_none() {
self.first_pack_error_pos = Some(loop_count);
}
super_iter.weird_iter_advance();
sub_iter.weird_iter_advance();
continue;
}
if !super_iter.weird_iter_good() && !sub_iter.weird_iter_good() {
let l_free_tail = unsafe {
(*super_tpv).tail.map_or(false, |t| {
!self
.log
.txn_log_get_mutable::<FreeTypePack, TypePackId>(
self.log.follow_type_pack_id(t),
)
.is_null()
})
};
let r_free_tail = unsafe {
(*sub_tpv).tail.map_or(false, |t| {
!self
.log
.txn_log_get_mutable::<FreeTypePack, TypePackId>(
self.log.follow_type_pack_id(t),
)
.is_null()
})
};
if l_free_tail && r_free_tail {
self.try_unify_type_pack_id_type_pack_id_bool(
unsafe { (*sub_tpv).tail.unwrap() },
unsafe { (*super_tpv).tail.unwrap() },
false,
);
} else if l_free_tail {
self.try_unify_type_pack_id_type_pack_id_bool(
empty_tp,
unsafe { (*super_tpv).tail.unwrap() },
false,
);
} else if r_free_tail {
self.try_unify_type_pack_id_type_pack_id_bool(
empty_tp,
unsafe { (*sub_tpv).tail.unwrap() },
false,
);
} else if unsafe { (*sub_tpv).tail.is_some() && (*super_tpv).tail.is_some() } {
if !self
.log
.txn_log_get_mutable::<VariadicTypePack, TypePackId>(super_iter.pack_id)
.is_null()
{
self.unifier_try_unify_variadics(
sub_iter.pack_id,
super_iter.pack_id,
false,
sub_iter.index as i32,
);
} else if !self
.log
.txn_log_get_mutable::<VariadicTypePack, TypePackId>(sub_iter.pack_id)
.is_null()
{
self.unifier_try_unify_variadics(
super_iter.pack_id,
sub_iter.pack_id,
true,
super_iter.index as i32,
);
} else {
self.try_unify_type_pack_id_type_pack_id_bool(
unsafe { (*sub_tpv).tail.unwrap() },
unsafe { (*super_tpv).tail.unwrap() },
false,
);
}
}
break;
}
if super_iter.weird_iter_can_grow() && sub_iter.weird_iter_can_grow() {
let s = unsafe { (*sub_iter.pack).tail.unwrap() };
let sup = unsafe { (*super_iter.pack).tail.unwrap() };
return self.try_unify_type_pack_id_type_pack_id_bool(s, sup, false);
}
if super_iter.weird_iter_can_grow() {
let new_tail = unsafe {
(*self.types).add_type_pack_type_pack_var(TypePackVar {
ty: TypePackVariant::TypePack(TypePack {
head: alloc::vec::Vec::new(),
tail: None,
}),
persistent: false,
owningArena: core::ptr::null_mut(),
})
};
super_iter.weird_iter_grow(new_tail);
} else if sub_iter.weird_iter_can_grow() {
let new_tail = unsafe {
(*self.types).add_type_pack_type_pack_var(TypePackVar {
ty: TypePackVariant::TypePack(TypePack {
head: alloc::vec::Vec::new(),
tail: None,
}),
persistent: false,
owningArena: core::ptr::null_mut(),
})
};
sub_iter.weird_iter_grow(new_tail);
} else {
if super_iter.weird_iter_good()
&& is_optional(*super_iter.weird_iter_operator_deref())
{
super_iter.weird_iter_advance();
continue;
} else if sub_iter.weird_iter_good()
&& is_optional(*sub_iter.weird_iter_operator_deref())
{
sub_iter.weird_iter_advance();
continue;
}
if !self
.log
.txn_log_get_mutable::<VariadicTypePack, TypePackId>(super_iter.pack_id)
.is_null()
{
self.unifier_try_unify_variadics(
sub_iter.pack_id,
super_iter.pack_id,
false,
sub_iter.index as i32,
);
return;
}
if !self
.log
.txn_log_get_mutable::<VariadicTypePack, TypePackId>(sub_iter.pack_id)
.is_null()
{
self.unifier_try_unify_variadics(
super_iter.pack_id,
sub_iter.pack_id,
true,
super_iter.index as i32,
);
return;
}
if !is_function_call && sub_iter.weird_iter_good() {
return;
}
let log_ptr = self.log_ptr();
let mut expected_size = size(super_tp, log_ptr);
let mut actual_size = size(sub_tp, log_ptr);
if self.ctx == CountMismatchContext::FunctionResult
|| self.ctx == CountMismatchContext::ExprListResult
{
core::mem::swap(&mut expected_size, &mut actual_size);
}
let ctx = self.ctx;
self.report_error_location_type_error_data(
self.location,
TypeErrorData::CountMismatch(CountMismatch {
expected: expected_size,
maximum: None,
actual: actual_size,
context: ctx,
is_variadic: false,
function: String::new(),
}),
);
let error_type = unsafe { (*self.builtin_types).errorType };
while super_iter.weird_iter_good() {
let cur = *super_iter.weird_iter_operator_deref();
self.try_unify_type_id_type_id_bool_bool_literal_properties(
cur, error_type, false, false, None,
);
super_iter.weird_iter_advance();
}
while sub_iter.weird_iter_good() {
let cur = *sub_iter.weird_iter_operator_deref();
self.try_unify_type_id_type_id_bool_bool_literal_properties(
cur, error_type, false, false, None,
);
sub_iter.weird_iter_advance();
}
return;
}
if no_infinite_growth {
break;
}
}
} else {
self.report_error_location_type_error_data(
self.location,
TypeErrorData::TypePackMismatch(TypePackMismatch {
wanted_tp: super_tp,
given_tp: sub_tp,
reason: String::new(),
}),
);
}
}
fn mk_fresh_for_iter(
&mut self,
scope: *mut crate::records::scope::Scope,
) -> crate::type_aliases::type_id::TypeId {
fresh_type(
unsafe { &mut *self.types },
unsafe { &*self.builtin_types },
scope,
Polarity::Positive,
)
}
#[inline]
fn log_ptr(&mut self) -> *mut crate::records::txn_log::TxnLog {
&mut self.log as *mut _
}
}