1use crate::enums::normalization_result::NormalizationResult;
3use crate::enums::variance::Variance;
4use crate::functions::get_type_alt_j::get_type_id;
5use crate::functions::is_blocked_unifier::is_blocked_txn_log_type_id;
6use crate::functions::is_prim::is_prim;
7use crate::records::any_type::AnyType;
8use crate::records::extern_type::ExternType;
9use crate::records::free_type::FreeType;
10use crate::records::function_type::FunctionType;
11use crate::records::generic_error::GenericError;
12use crate::records::generic_type::GenericType;
13use crate::records::intersection_type::IntersectionType;
14use crate::records::metatable_type::MetatableType;
15use crate::records::negation_type::NegationType;
16use crate::records::never_type::NeverType;
17use crate::records::primitive_type::{PrimitiveType, Type as PrimType};
18use crate::records::r#type::Type;
19use crate::records::singleton_type::SingletonType;
20use crate::records::substitution::Substitution;
21use crate::records::table_type::TableType;
22use crate::records::txn_log::TxnLog;
23use crate::records::type_function_instance_type::TypeFunctionInstanceType;
24use crate::records::type_mismatch::TypeMismatch;
25use crate::records::unifier::Unifier;
26use crate::records::unknown_type::UnknownType;
27use crate::records::widen::Widen;
28use crate::type_aliases::error_type::ErrorType;
29use crate::type_aliases::literal_properties::LiteralProperties;
30use crate::type_aliases::type_error_data::TypeErrorData;
31use crate::type_aliases::type_id::TypeId;
32use crate::type_aliases::type_variant::TypeVariant;
33use alloc::string::String;
34
35impl Unifier {
36 pub fn try_unify_type_id_type_id_bool_bool_literal_properties(
38 &mut self,
39 mut sub_ty: TypeId,
40 mut super_ty: TypeId,
41 is_function_call: bool,
42 is_intersection: bool,
43 literal_properties: Option<&LiteralProperties>,
44 ) {
45 unsafe {
46 (*self.shared_state).counters.iteration_count += 1;
47 if (*self.shared_state).counters.iteration_limit > 0
48 && (*self.shared_state).counters.iteration_limit
49 < (*self.shared_state).counters.iteration_count
50 {
51 self.report_error_location_type_error_data(
52 self.location,
53 TypeErrorData::UnificationTooComplex(
54 crate::records::unification_too_complex::UnificationTooComplex::default(),
55 ),
56 );
57 return;
58 }
59 }
60
61 super_ty = self.log.follow_type_id(super_ty);
62 sub_ty = self.log.follow_type_id(sub_ty);
63
64 if super_ty == sub_ty {
65 return;
66 }
67
68 if self.reflexive_equal_type_id(super_ty, sub_ty, 32) {
75 return;
76 }
77
78 let sub_blocked = is_blocked_txn_log_type_id(&self.log, sub_ty);
79 let super_blocked = is_blocked_txn_log_type_id(&self.log, super_ty);
80 if sub_blocked && super_blocked {
81 self.blocked_types.push(sub_ty);
82 self.blocked_types.push(super_ty);
83 } else if sub_blocked {
84 self.blocked_types.push(sub_ty);
85 } else if super_blocked {
86 self.blocked_types.push(super_ty);
87 }
88
89 if !self
90 .log
91 .txn_log_get::<TypeFunctionInstanceType, TypeId>(super_ty)
92 .is_null()
93 {
94 self.ice_string("Unexpected TypeFunctionInstanceType superTy");
95 }
96
97 if !self
98 .log
99 .txn_log_get::<TypeFunctionInstanceType, TypeId>(sub_ty)
100 .is_null()
101 {
102 self.ice_string("Unexpected TypeFunctionInstanceType subTy");
103 }
104
105 let super_free = self.log.txn_log_get_mutable::<FreeType, TypeId>(super_ty);
106 let sub_free = self.log.txn_log_get_mutable::<FreeType, TypeId>(sub_ty);
107
108 if !super_free.is_null()
111 && !sub_free.is_null()
112 && unsafe { (*super_free).level.subsumes(&(*sub_free).level) }
113 {
114 if !self.occurs_check_type_id_type_id_bool(sub_ty, super_ty, false) {
115 self.log
116 .replace_type_id_t(sub_ty, Type::new(TypeVariant::Bound(super_ty)));
117 }
118 return;
119 } else if !super_free.is_null() && !sub_free.is_null() {
120 if !self.occurs_check_type_id_type_id_bool(super_ty, sub_ty, true) {
121 if unsafe { (*super_free).level.subsumes(&(*sub_free).level) } {
122 self.log
123 .change_level_type_id_type_level(sub_ty, unsafe { (*super_free).level });
124 }
125 self.log
126 .replace_type_id_t(super_ty, Type::new(TypeVariant::Bound(sub_ty)));
127 }
128 return;
129 } else if !super_free.is_null() {
130 let sub_generic = self.log.txn_log_get_mutable::<GenericType, TypeId>(sub_ty);
132 if !sub_generic.is_null()
133 && !unsafe { (*sub_generic).level.subsumes(&(*super_free).level) }
134 {
135 self.report_error_location_type_error_data(
136 self.location,
137 TypeErrorData::GenericError(GenericError::new(String::from(
138 "Generic subtype escaping scope",
139 ))),
140 );
141 return;
142 }
143
144 if !self.occurs_check_type_id_type_id_bool(super_ty, sub_ty, true) {
145 let super_level = unsafe { (*super_free).level };
146 crate::functions::promote_type_levels_unifier::promote_type_levels_txn_log_type_arena_type_level_type_id(
147 &mut self.log,
148 unsafe { &*self.types },
149 super_level,
150 sub_ty,
151 );
152
153 let mut widen = Widen::widen_widen(self.types, self.builtin_types);
154 let widened = widen.operator_call_mut(sub_ty);
155 self.log
156 .replace_type_id_t(super_ty, Type::new(TypeVariant::Bound(widened)));
157 }
158 return;
159 } else if !sub_free.is_null() {
160 if !self
163 .log
164 .txn_log_get::<UnknownType, TypeId>(super_ty)
165 .is_null()
166 {
167 return;
168 }
169
170 let super_generic = self
171 .log
172 .txn_log_get_mutable::<GenericType, TypeId>(super_ty);
173 if !super_generic.is_null()
174 && !unsafe { (*super_generic).level.subsumes(&(*sub_free).level) }
175 {
176 self.report_error_location_type_error_data(
177 self.location,
178 TypeErrorData::GenericError(GenericError::new(String::from(
179 "Generic supertype escaping scope",
180 ))),
181 );
182 return;
183 }
184
185 if !self.occurs_check_type_id_type_id_bool(sub_ty, super_ty, false) {
186 let sub_level = unsafe { (*sub_free).level };
187 crate::functions::promote_type_levels_unifier::promote_type_levels_txn_log_type_arena_type_level_type_id(
188 &mut self.log,
189 unsafe { &*self.types },
190 sub_level,
191 super_ty,
192 );
193 self.log
194 .replace_type_id_t(sub_ty, Type::new(TypeVariant::Bound(super_ty)));
195 }
196 return;
197 }
198
199 if !self.log.txn_log_get::<AnyType, TypeId>(super_ty).is_null() {
200 return self.try_unify_with_any_type_id_type_id(sub_ty, unsafe {
201 (*self.builtin_types).anyType
202 });
203 }
204
205 if !self.log.txn_log_get::<AnyType, TypeId>(sub_ty).is_null() {
206 if self.normalize {
207 let super_norm = unsafe { (*self.normalizer).normalize(super_ty) };
209 if !unsafe { get_type_id::<AnyType>(super_norm.tops) }.is_null() {
210 } else {
212 self.failure = true;
213 }
214 } else {
215 self.failure = true;
216 }
217 return self.try_unify_with_any_type_id_type_id(super_ty, unsafe {
218 (*self.builtin_types).anyType
219 });
220 }
221
222 if !self.log.txn_log_get::<NeverType, TypeId>(sub_ty).is_null() {
223 return self.try_unify_with_any_type_id_type_id(super_ty, unsafe {
224 (*self.builtin_types).neverType
225 });
226 }
227
228 let cache_enabled =
230 !is_function_call && !is_intersection && self.variance == Variance::Invariant;
231
232 if cache_enabled {
233 if unsafe {
234 (*self.shared_state)
235 .cached_unify
236 .find(&(sub_ty, super_ty))
237 .is_some()
238 } {
239 return;
240 }
241
242 if let Some(error) = unsafe {
248 (*self.shared_state)
249 .cached_unify_error
250 .find(&(sub_ty, super_ty))
251 .cloned()
252 } {
253 self.report_error_location_type_error_data(self.location, error);
254 return;
255 }
256 }
257
258 if self.log.have_seen_type_id_type_id(super_ty, sub_ty) {
260 return;
261 }
262
263 self.log.push_seen_type_id_type_id(super_ty, sub_ty);
264
265 let error_count = self.errors.len();
266
267 let sub_union = self
268 .log
269 .txn_log_get_mutable::<crate::records::union_type::UnionType, TypeId>(sub_ty);
270 let super_intersection = self
271 .log
272 .txn_log_get_mutable::<IntersectionType, TypeId>(super_ty);
273 let super_union = self
274 .log
275 .txn_log_get_mutable::<crate::records::union_type::UnionType, TypeId>(super_ty);
276 let sub_intersection = self
277 .log
278 .txn_log_get_mutable::<IntersectionType, TypeId>(sub_ty);
279
280 if !sub_union.is_null() {
281 self.unifier_try_unify_union_with_type(sub_ty, sub_union, super_ty);
282 } else if !super_intersection.is_null() {
283 self.unifier_try_unify_type_with_intersection(sub_ty, super_ty, super_intersection);
284 } else if !super_union.is_null() {
285 self.unifier_try_unify_type_with_union(
286 sub_ty,
287 super_ty,
288 super_union,
289 cache_enabled,
290 is_function_call,
291 );
292 } else if !sub_intersection.is_null() {
293 self.unifier_try_unify_intersection_with_type(
294 sub_ty,
295 sub_intersection,
296 super_ty,
297 cache_enabled,
298 is_function_call,
299 );
300 } else if !self.log.txn_log_get::<AnyType, TypeId>(sub_ty).is_null() {
301 self.try_unify_with_any_type_id_type_id(super_ty, unsafe {
302 (*self.builtin_types).unknownType
303 });
304 self.failure = true;
305 } else if !self.log.txn_log_get::<ErrorType, TypeId>(sub_ty).is_null()
306 && !self
307 .log
308 .txn_log_get::<ErrorType, TypeId>(super_ty)
309 .is_null()
310 {
311 } else if !self
313 .log
314 .txn_log_get::<ErrorType, TypeId>(super_ty)
315 .is_null()
316 {
317 self.try_unify_with_any_type_id_type_id(sub_ty, unsafe {
318 (*self.builtin_types).errorType
319 });
320 self.failure = true;
321 } else if !self.log.txn_log_get::<ErrorType, TypeId>(sub_ty).is_null() {
322 self.try_unify_with_any_type_id_type_id(super_ty, unsafe {
323 (*self.builtin_types).errorType
324 });
325 self.failure = true;
326 } else if !self
327 .log
328 .txn_log_get::<UnknownType, TypeId>(super_ty)
329 .is_null()
330 {
331 self.try_unify_with_any_type_id_type_id(sub_ty, unsafe {
333 (*self.builtin_types).unknownType
334 });
335 } else if !self
336 .log
337 .txn_log_get_mutable::<PrimitiveType, TypeId>(super_ty)
338 .is_null()
339 && !self
340 .log
341 .txn_log_get_mutable::<PrimitiveType, TypeId>(sub_ty)
342 .is_null()
343 {
344 self.unifier_try_unify_primitives(sub_ty, super_ty);
345 } else if (!self
346 .log
347 .txn_log_get_mutable::<PrimitiveType, TypeId>(super_ty)
348 .is_null()
349 || !self
350 .log
351 .txn_log_get_mutable::<SingletonType, TypeId>(super_ty)
352 .is_null())
353 && !self
354 .log
355 .txn_log_get_mutable::<SingletonType, TypeId>(sub_ty)
356 .is_null()
357 {
358 self.unifier_try_unify_singletons(sub_ty, super_ty);
359 } else if {
360 let ptv = unsafe { get_type_id::<PrimitiveType>(super_ty) };
361 !ptv.is_null()
362 && unsafe { (*ptv).r#type } == PrimType::Function
363 && !unsafe { get_type_id::<FunctionType>(sub_ty) }.is_null()
364 } {
365 } else if is_prim(super_ty, PrimType::Table)
367 && (!unsafe { get_type_id::<TableType>(sub_ty) }.is_null()
368 || !unsafe { get_type_id::<MetatableType>(sub_ty) }.is_null())
369 {
370 } else if !self
372 .log
373 .txn_log_get_mutable::<FunctionType, TypeId>(super_ty)
374 .is_null()
375 && !self
376 .log
377 .txn_log_get_mutable::<FunctionType, TypeId>(sub_ty)
378 .is_null()
379 {
380 self.unifier_try_unify_functions(sub_ty, super_ty, is_function_call);
381 } else if {
382 let table = self.log.txn_log_get::<PrimitiveType, TypeId>(super_ty);
383 !table.is_null() && unsafe { (*table).r#type } == PrimType::Table
384 } {
385 let empty_table = unsafe { (*self.builtin_types).emptyTableType };
386 self.try_unify_type_id_type_id_bool_bool_literal_properties_entry(
387 sub_ty,
388 empty_table,
389 is_function_call,
390 is_intersection,
391 None,
392 );
393 } else if {
394 let table = self.log.txn_log_get::<PrimitiveType, TypeId>(sub_ty);
395 !table.is_null() && unsafe { (*table).r#type } == PrimType::Table
396 } {
397 let empty_table = unsafe { (*self.builtin_types).emptyTableType };
398 self.try_unify_type_id_type_id_bool_bool_literal_properties_entry(
399 empty_table,
400 super_ty,
401 is_function_call,
402 is_intersection,
403 None,
404 );
405 } else if !self
406 .log
407 .txn_log_get_mutable::<TableType, TypeId>(super_ty)
408 .is_null()
409 && !self
410 .log
411 .txn_log_get_mutable::<TableType, TypeId>(sub_ty)
412 .is_null()
413 {
414 self.unifier_try_unify_tables(
415 sub_ty,
416 super_ty,
417 is_intersection,
418 literal_properties.map_or(core::ptr::null(), |lp| lp as *const LiteralProperties),
419 );
420 } else if !self
421 .log
422 .txn_log_get::<TableType, TypeId>(super_ty)
423 .is_null()
424 && (!self
425 .log
426 .txn_log_get::<PrimitiveType, TypeId>(sub_ty)
427 .is_null()
428 || !self
429 .log
430 .txn_log_get::<SingletonType, TypeId>(sub_ty)
431 .is_null())
432 {
433 self.unifier_try_unify_scalar_shape(sub_ty, super_ty, false);
434 } else if !self.log.txn_log_get::<TableType, TypeId>(sub_ty).is_null()
435 && (!self
436 .log
437 .txn_log_get::<PrimitiveType, TypeId>(super_ty)
438 .is_null()
439 || !self
440 .log
441 .txn_log_get::<SingletonType, TypeId>(super_ty)
442 .is_null())
443 {
444 self.unifier_try_unify_scalar_shape(sub_ty, super_ty, true);
445 } else if !self
446 .log
447 .txn_log_get_mutable::<MetatableType, TypeId>(super_ty)
448 .is_null()
449 {
450 self.unifier_try_unify_with_metatable(sub_ty, super_ty, false);
451 } else if !self
452 .log
453 .txn_log_get_mutable::<MetatableType, TypeId>(sub_ty)
454 .is_null()
455 {
456 self.unifier_try_unify_with_metatable(super_ty, sub_ty, true);
457 } else if !self
458 .log
459 .txn_log_get_mutable::<ExternType, TypeId>(super_ty)
460 .is_null()
461 {
462 self.unifier_try_unify_with_extern_type(sub_ty, super_ty, false);
463 } else if !self
464 .log
465 .txn_log_get_mutable::<ExternType, TypeId>(sub_ty)
466 .is_null()
467 {
468 self.unifier_try_unify_with_extern_type(sub_ty, super_ty, true);
469 } else if !self
470 .log
471 .txn_log_get::<NegationType, TypeId>(super_ty)
472 .is_null()
473 || !self
474 .log
475 .txn_log_get::<NegationType, TypeId>(sub_ty)
476 .is_null()
477 {
478 self.unifier_try_unify_negations(sub_ty, super_ty);
479 } else if self.check_inhabited
480 && unsafe { (*self.normalizer).is_inhabited_type_id(sub_ty) }
481 == NormalizationResult::False
482 {
483 } else {
485 let context = self.unifier_mismatch_context();
486 self.report_error_location_type_error_data(
487 self.location,
488 TypeErrorData::TypeMismatch(TypeMismatch {
489 wanted_type: super_ty,
490 given_type: sub_ty,
491 reason: String::new(),
492 error: None,
493 context,
494 }),
495 );
496 }
497
498 if cache_enabled {
499 self.unifier_cache_result(sub_ty, super_ty, error_count);
500 }
501
502 self.log.pop_seen_type_id_type_id(super_ty, sub_ty);
503 }
504}