luaur_analysis/methods/
unifier_2_unify_unifier_2_alt_c.rs1use crate::enums::unify_result::UnifyResult;
5use crate::functions::follow_type::follow_type_id;
6use crate::functions::get_mutable_type::get_mutable_type_id;
7use crate::functions::get_type_alt_j::get_type_id;
8use crate::functions::is_irresolvable_unifier_2::is_irresolvable;
9use crate::records::any_type::AnyType;
10use crate::records::free_type::FreeType;
11use crate::records::function_type::FunctionType;
12use crate::records::intersection_type::IntersectionType;
13use crate::records::metatable_type::MetatableType;
14use crate::records::negation_type::NegationType;
15use crate::records::never_type::NeverType;
16use crate::records::non_exceptional_recursion_limiter::NonExceptionalRecursionLimiter;
17use crate::records::subtype_constraint::SubtypeConstraint;
18use crate::records::table_type::TableType;
19use crate::records::unifier_2::Unifier2;
20use crate::records::union_type::UnionType;
21use crate::records::unknown_type::UnknownType;
22use crate::type_aliases::constraint_v::ConstraintV;
23use crate::type_aliases::type_id::TypeId;
24use luaur_common::{FFlag, FInt};
25
26impl Unifier2 {
27 pub fn unify_type_id_type_id(
28 &mut self,
29 mut sub_ty: TypeId,
30 mut super_ty: TypeId,
31 ) -> UnifyResult {
32 if FInt::LuauTypeInferIterationLimit.get() > 0
33 && self.iteration_count >= FInt::LuauTypeInferIterationLimit.get() as i32
34 {
35 return UnifyResult::TooComplex;
36 }
37
38 self.iteration_count += 1;
39
40 if FFlag::LuauLimitUnificationRecursion.get() {
44 self.recursion_count += 1;
46 let mut nerl = NonExceptionalRecursionLimiter {
47 base: unsafe { core::mem::zeroed() },
48 native_stack_guard: unsafe { core::mem::zeroed() },
49 };
50 nerl.non_exceptional_recursion_limiter_non_exceptional_recursion_limiter(
51 &mut self.recursion_count as *mut i32 as *mut core::ffi::c_int,
52 );
53 if !nerl.is_ok(self.recursion_limit as core::ffi::c_int) {
54 return UnifyResult::TooComplex;
55 }
56 }
57
58 sub_ty = unsafe { follow_type_id(sub_ty) };
59 super_ty = unsafe { follow_type_id(super_ty) };
60
61 if let Some(sub_gen) = self.generic_substitutions.find(&sub_ty) {
62 let sub_gen = *sub_gen;
63 return self.unify_type_id_type_id(sub_gen, super_ty);
64 }
65
66 if let Some(super_gen) = self.generic_substitutions.find(&super_ty) {
67 let super_gen = *super_gen;
68 return self.unify_type_id_type_id(sub_ty, super_gen);
69 }
70
71 if self.seen_type_pairings.contains(&(sub_ty, super_ty)) {
72 return UnifyResult::Ok;
73 }
74 self.seen_type_pairings.insert((sub_ty, super_ty));
75
76 if sub_ty == super_ty {
77 return UnifyResult::Ok;
78 }
79
80 if (is_irresolvable(sub_ty) || is_irresolvable(super_ty))
88 && unsafe { get_type_id::<NeverType>(sub_ty) }.is_null()
89 && unsafe { get_type_id::<UnknownType>(super_ty) }.is_null()
90 {
91 if !self.uninhabited_type_functions.is_null()
92 && unsafe {
93 (*self.uninhabited_type_functions)
94 .contains(&(sub_ty as *const core::ffi::c_void))
95 || (*self.uninhabited_type_functions)
96 .contains(&(super_ty as *const core::ffi::c_void))
97 }
98 {
99 return UnifyResult::Ok;
100 }
101
102 self.incomplete_subtypes
103 .push(ConstraintV::Subtype(SubtypeConstraint {
104 sub_type: sub_ty,
105 super_type: super_ty,
106 }));
107 return UnifyResult::Ok;
108 }
109
110 let sub_free = unsafe { get_mutable_type_id::<FreeType>(sub_ty) };
111 let super_free = unsafe { get_mutable_type_id::<FreeType>(super_ty) };
112
113 if !super_free.is_null() {
114 let instantiated = self.instantiate_with_bound_types(sub_ty);
115 let new_lower = self.mk_union(unsafe { (*super_free).lower_bound }, instantiated);
116 unsafe {
117 (*super_free).lower_bound = new_lower;
118 }
119 }
120
121 if !sub_free.is_null() {
122 return self.unify_free_with_type(sub_ty, super_ty);
123 }
124
125 if !sub_free.is_null() || !super_free.is_null() {
126 return UnifyResult::Ok;
127 }
128
129 let sub_fn = unsafe { get_type_id::<FunctionType>(sub_ty) };
130 let super_fn = unsafe { get_type_id::<FunctionType>(super_ty) };
131 if !sub_fn.is_null() && !super_fn.is_null() {
132 return self.unify_type_id_function_type(sub_ty, unsafe { &*super_fn });
133 }
134
135 let sub_union = unsafe { get_type_id::<UnionType>(sub_ty) };
136 let super_union = unsafe { get_type_id::<UnionType>(super_ty) };
137 if !sub_union.is_null() {
138 return self.unify_union_type_type_id(unsafe { &*sub_union }, super_ty);
139 } else if !super_union.is_null() {
140 return self.unify_type_id_union_type(sub_ty, unsafe { &*super_union });
141 }
142
143 let sub_intersection = unsafe { get_type_id::<IntersectionType>(sub_ty) };
144 let super_intersection = unsafe { get_type_id::<IntersectionType>(super_ty) };
145 if !sub_intersection.is_null() {
146 return self.unify_intersection_type_type_id(unsafe { &*sub_intersection }, super_ty);
147 } else if !super_intersection.is_null() {
148 return self.unify_type_id_intersection_type(sub_ty, unsafe { &*super_intersection });
149 }
150
151 let sub_never = unsafe { get_type_id::<NeverType>(sub_ty) };
152 let super_never = unsafe { get_type_id::<NeverType>(super_ty) };
153 if !sub_never.is_null() && !super_never.is_null() {
154 return UnifyResult::Ok;
155 } else if !sub_never.is_null() && !super_fn.is_null() {
156 let builtin_types = unsafe { &*self.builtin_types.as_ptr() };
158 let never_pack = builtin_types.neverTypePack;
159 let super_fn_ref = unsafe { &*super_fn };
160 let arg_result =
161 self.unify_type_pack_id_type_pack_id(super_fn_ref.arg_types, never_pack);
162 let ret_result =
163 self.unify_type_pack_id_type_pack_id(never_pack, super_fn_ref.ret_types);
164 return arg_result & ret_result;
165 } else if !sub_fn.is_null() && !super_never.is_null() {
166 let builtin_types = unsafe { &*self.builtin_types.as_ptr() };
168 let never_pack = builtin_types.neverTypePack;
169 let sub_fn_ref = unsafe { &*sub_fn };
170 let arg_result = self.unify_type_pack_id_type_pack_id(never_pack, sub_fn_ref.arg_types);
171 let ret_result = self.unify_type_pack_id_type_pack_id(sub_fn_ref.ret_types, never_pack);
172 return arg_result & ret_result;
173 }
174
175 let sub_any = unsafe { get_type_id::<AnyType>(sub_ty) };
176 let super_any = unsafe { get_type_id::<AnyType>(super_ty) };
177
178 let sub_table = unsafe { get_mutable_type_id::<TableType>(sub_ty) };
179 let super_table = unsafe { get_type_id::<TableType>(super_ty) };
180
181 if !sub_any.is_null() && !super_any.is_null() {
182 return UnifyResult::Ok;
183 } else if !sub_any.is_null() && !super_fn.is_null() {
184 return self.unify_any_type_function_type(unsafe { &*sub_any }, unsafe { &*super_fn });
185 } else if !sub_fn.is_null() && !super_any.is_null() {
186 return self.unify_function_type_any_type(unsafe { &*sub_fn }, unsafe { &*super_any });
187 } else if !sub_any.is_null() && !super_table.is_null() {
188 return self.unify_any_type_table_type(unsafe { &*sub_any }, unsafe { &*super_table });
189 } else if !sub_table.is_null() && !super_any.is_null() {
190 return self.unify_table_type_any_type(unsafe { &*sub_table }, unsafe { &*super_any });
191 }
192
193 if !sub_table.is_null() && !super_table.is_null() {
194 luaur_common::macros::luau_assert::LUAU_ASSERT!(
199 unsafe { (*sub_table).bound_to }.is_none()
200 );
201 luaur_common::macros::luau_assert::LUAU_ASSERT!(
202 unsafe { (*super_table).bound_to }.is_none()
203 );
204
205 return self
206 .unify_table_type_table_type(unsafe { &mut *sub_table }, unsafe { &*super_table });
207 }
208
209 let sub_metatable = unsafe { get_type_id::<MetatableType>(sub_ty) };
210 let super_metatable = unsafe { get_type_id::<MetatableType>(super_ty) };
211 if !sub_metatable.is_null() && !super_metatable.is_null() {
212 return self.unify_metatable_type_metatable_type(unsafe { &*sub_metatable }, unsafe {
213 &*super_metatable
214 });
215 } else if !sub_metatable.is_null() && !super_any.is_null() {
216 return self
217 .unify_metatable_type_any_type(unsafe { &*sub_metatable }, unsafe { &*super_any });
218 } else if !sub_any.is_null() && !super_metatable.is_null() {
219 return self
220 .unify_any_type_metatable_type(unsafe { &*sub_any }, unsafe { &*super_metatable });
221 } else if !sub_metatable.is_null() {
222 let inner = unsafe { (*sub_metatable).table() };
224 return self.unify_type_id_type_id(inner, super_ty);
225 } else if !super_metatable.is_null() {
226 let inner = unsafe { (*super_metatable).table() };
228 return self.unify_type_id_type_id(sub_ty, inner);
229 }
230
231 let sub_negation = unsafe { get_type_id::<NegationType>(sub_ty) };
232 let super_negation = unsafe { get_type_id::<NegationType>(super_ty) };
233 if !sub_negation.is_null() && !super_negation.is_null() {
234 return self.unify_type_id_type_id(unsafe { (*sub_negation).ty }, unsafe {
235 (*super_negation).ty
236 });
237 }
238
239 UnifyResult::Ok
241 }
242}