1use crate::enums::polarity::Polarity;
3use crate::functions::flatten_type_pack_alt_b::flatten;
4use crate::functions::fresh_type::fresh_type;
5use crate::functions::is_blocked_unifier_alt_c::is_blocked_txn_log_type_pack_id;
6use crate::functions::is_optional::is_optional;
7use crate::functions::size_type_pack::size;
8use crate::records::count_mismatch::{CountMismatch, CountMismatchContext};
9use crate::records::free_type_pack::FreeTypePack;
10use crate::records::type_pack::TypePack;
11use crate::records::type_pack_mismatch::TypePackMismatch;
12use crate::records::type_pack_var::TypePackVar;
13use crate::records::unifier::Unifier;
14use crate::records::variadic_type_pack::VariadicTypePack;
15use crate::records::weird_iter::WeirdIter;
16use crate::records::widen::Widen;
17use crate::type_aliases::error_type_pack::ErrorTypePack;
18use crate::type_aliases::type_error_data::TypeErrorData;
19use crate::type_aliases::type_pack_id::TypePackId;
20use crate::type_aliases::type_pack_variant::TypePackVariant;
21use alloc::string::String;
22
23impl Unifier {
24 pub fn try_unify_type_pack_id_type_pack_id_bool(
26 &mut self,
27 mut sub_tp: TypePackId,
28 mut super_tp: TypePackId,
29 is_function_call: bool,
30 ) {
31 unsafe {
32 (*self.shared_state).counters.iteration_count += 1;
33 if (*self.shared_state).counters.iteration_limit > 0
34 && (*self.shared_state).counters.iteration_limit
35 < (*self.shared_state).counters.iteration_count
36 {
37 self.report_error_location_type_error_data(
38 self.location,
39 TypeErrorData::UnificationTooComplex(
40 crate::records::unification_too_complex::UnificationTooComplex::default(),
41 ),
42 );
43 return;
44 }
45 }
46
47 super_tp = self.log.follow_type_pack_id(super_tp);
48 sub_tp = self.log.follow_type_pack_id(sub_tp);
49
50 if self.reflexive_equal_type_pack_id(super_tp, sub_tp, 32) {
55 return;
56 }
57
58 loop {
59 let tp = self.log.txn_log_get_mutable::<TypePack, TypePackId>(sub_tp);
60 if tp.is_null() {
61 break;
62 }
63 if unsafe { (*tp).head.is_empty() && (*tp).tail.is_some() } {
64 sub_tp = self.log.follow_type_pack_id(unsafe { (*tp).tail.unwrap() });
65 } else {
66 break;
67 }
68 }
69
70 loop {
71 let tp = self
72 .log
73 .txn_log_get_mutable::<TypePack, TypePackId>(super_tp);
74 if tp.is_null() {
75 break;
76 }
77 if unsafe { (*tp).head.is_empty() && (*tp).tail.is_some() } {
78 super_tp = self.log.follow_type_pack_id(unsafe { (*tp).tail.unwrap() });
79 } else {
80 break;
81 }
82 }
83
84 if super_tp == sub_tp {
85 return;
86 }
87
88 if self
89 .log
90 .have_seen_type_pack_id_type_pack_id(super_tp, sub_tp)
91 {
92 return;
93 }
94
95 let sub_blocked = is_blocked_txn_log_type_pack_id(&self.log, sub_tp);
96 let super_blocked = is_blocked_txn_log_type_pack_id(&self.log, super_tp);
97 if sub_blocked && super_blocked {
98 self.blocked_type_packs.push(sub_tp);
99 self.blocked_type_packs.push(super_tp);
100 } else if sub_blocked {
101 self.blocked_type_packs.push(sub_tp);
102 } else if super_blocked {
103 self.blocked_type_packs.push(super_tp);
104 }
105
106 if !self
107 .log
108 .txn_log_get_mutable::<FreeTypePack, TypePackId>(super_tp)
109 .is_null()
110 {
111 if !self.occurs_check_type_pack_id_type_pack_id_bool(super_tp, sub_tp, true) {
112 let mut widen = Widen::widen_widen(self.types, self.builtin_types);
113 let widened = widen.operator_call(sub_tp);
114 let bound = TypePackVar {
115 ty: TypePackVariant::Bound(widened),
116 persistent: false,
117 owningArena: core::ptr::null_mut(),
118 };
119 self.log.replace_type_pack_id_type_pack_var(super_tp, bound);
120 }
121 } else if !self
122 .log
123 .txn_log_get_mutable::<FreeTypePack, TypePackId>(sub_tp)
124 .is_null()
125 {
126 if !self.occurs_check_type_pack_id_type_pack_id_bool(sub_tp, super_tp, false) {
127 let bound = TypePackVar {
128 ty: TypePackVariant::Bound(super_tp),
129 persistent: false,
130 owningArena: core::ptr::null_mut(),
131 };
132 self.log.replace_type_pack_id_type_pack_var(sub_tp, bound);
133 }
134 } else if !self
135 .log
136 .txn_log_get_mutable::<ErrorTypePack, TypePackId>(super_tp)
137 .is_null()
138 {
139 self.try_unify_with_any_type_pack_id_type_pack_id(sub_tp, super_tp);
140 } else if !self
141 .log
142 .txn_log_get_mutable::<ErrorTypePack, TypePackId>(sub_tp)
143 .is_null()
144 {
145 self.try_unify_with_any_type_pack_id_type_pack_id(super_tp, sub_tp);
146 } else if !self
147 .log
148 .txn_log_get_mutable::<VariadicTypePack, TypePackId>(super_tp)
149 .is_null()
150 {
151 self.unifier_try_unify_variadics(sub_tp, super_tp, false, 0);
152 } else if !self
153 .log
154 .txn_log_get_mutable::<VariadicTypePack, TypePackId>(sub_tp)
155 .is_null()
156 {
157 self.unifier_try_unify_variadics(super_tp, sub_tp, true, 0);
158 } else if !self
159 .log
160 .txn_log_get_mutable::<TypePack, TypePackId>(super_tp)
161 .is_null()
162 && !self
163 .log
164 .txn_log_get_mutable::<TypePack, TypePackId>(sub_tp)
165 .is_null()
166 {
167 let super_tpv = self
168 .log
169 .txn_log_get_mutable::<TypePack, TypePackId>(super_tp);
170 let sub_tpv = self.log.txn_log_get_mutable::<TypePack, TypePackId>(sub_tp);
171
172 let (super_types, super_tail) = flatten(super_tp, &self.log);
175 let (sub_types, sub_tail) = flatten(sub_tp, &self.log);
176
177 let no_infinite_growth = (super_types.len() != sub_types.len())
178 && super_tail.map_or(false, |t| {
179 !self
180 .log
181 .txn_log_get_mutable::<FreeTypePack, TypePackId>(t)
182 .is_null()
183 })
184 && sub_tail.map_or(false, |t| {
185 !self
186 .log
187 .txn_log_get_mutable::<FreeTypePack, TypePackId>(t)
188 .is_null()
189 });
190
191 let mut super_iter = WeirdIter {
192 pack_id: super_tp,
193 log: &mut self.log as *mut _,
194 pack: core::ptr::null_mut(),
195 index: 0,
196 growing: false,
197 level: crate::records::type_level::TypeLevel::default(),
198 scope: core::ptr::null_mut(),
199 };
200 super_iter.weird_iter_type_pack_id_txn_log(super_tp, unsafe { &mut *(self.log_ptr()) });
201
202 let mut sub_iter = WeirdIter {
203 pack_id: sub_tp,
204 log: &mut self.log as *mut _,
205 pack: core::ptr::null_mut(),
206 index: 0,
207 growing: false,
208 level: crate::records::type_level::TypeLevel::default(),
209 scope: core::ptr::null_mut(),
210 };
211 sub_iter.weird_iter_type_pack_id_txn_log(sub_tp, unsafe { &mut *(self.log_ptr()) });
212
213 super_iter.scope = self.scope;
214 sub_iter.scope = self.scope;
215
216 let empty_tp = unsafe {
217 (*self.types).add_type_pack_t(TypePack {
218 head: alloc::vec::Vec::new(),
219 tail: None,
220 })
221 };
222
223 let mut loop_count = 0;
224
225 loop {
226 if luaur_common::FInt::LuauTypeInferTypePackLoopLimit.get() > 0
227 && loop_count >= luaur_common::FInt::LuauTypeInferTypePackLoopLimit.get()
228 {
229 self.ice_string("Detected possibly infinite TypePack growth");
230 }
231
232 loop_count += 1;
233
234 if super_iter.weird_iter_good() && sub_iter.growing {
235 let ft = self.mk_fresh_for_iter(sub_iter.scope);
236 sub_iter.weird_iter_push_type(ft);
237 }
238
239 if sub_iter.weird_iter_good() && super_iter.growing {
240 let ft = self.mk_fresh_for_iter(super_iter.scope);
241 super_iter.weird_iter_push_type(ft);
242 }
243
244 if super_iter.weird_iter_good() && sub_iter.weird_iter_good() {
245 let s = *sub_iter.weird_iter_operator_deref();
246 let sup = *super_iter.weird_iter_operator_deref();
247 self.try_unify_type_id_type_id_bool_bool_literal_properties(
248 s, sup, false, false, None,
249 );
250
251 if !self.errors.is_empty() && self.first_pack_error_pos.is_none() {
252 self.first_pack_error_pos = Some(loop_count);
253 }
254
255 super_iter.weird_iter_advance();
256 sub_iter.weird_iter_advance();
257 continue;
258 }
259
260 if !super_iter.weird_iter_good() && !sub_iter.weird_iter_good() {
262 let l_free_tail = unsafe {
263 (*super_tpv).tail.map_or(false, |t| {
264 !self
265 .log
266 .txn_log_get_mutable::<FreeTypePack, TypePackId>(
267 self.log.follow_type_pack_id(t),
268 )
269 .is_null()
270 })
271 };
272 let r_free_tail = unsafe {
273 (*sub_tpv).tail.map_or(false, |t| {
274 !self
275 .log
276 .txn_log_get_mutable::<FreeTypePack, TypePackId>(
277 self.log.follow_type_pack_id(t),
278 )
279 .is_null()
280 })
281 };
282 if l_free_tail && r_free_tail {
283 self.try_unify_type_pack_id_type_pack_id_bool(
284 unsafe { (*sub_tpv).tail.unwrap() },
285 unsafe { (*super_tpv).tail.unwrap() },
286 false,
287 );
288 } else if l_free_tail {
289 self.try_unify_type_pack_id_type_pack_id_bool(
290 empty_tp,
291 unsafe { (*super_tpv).tail.unwrap() },
292 false,
293 );
294 } else if r_free_tail {
295 self.try_unify_type_pack_id_type_pack_id_bool(
296 empty_tp,
297 unsafe { (*sub_tpv).tail.unwrap() },
298 false,
299 );
300 } else if unsafe { (*sub_tpv).tail.is_some() && (*super_tpv).tail.is_some() } {
301 if !self
302 .log
303 .txn_log_get_mutable::<VariadicTypePack, TypePackId>(super_iter.pack_id)
304 .is_null()
305 {
306 self.unifier_try_unify_variadics(
307 sub_iter.pack_id,
308 super_iter.pack_id,
309 false,
310 sub_iter.index as i32,
311 );
312 } else if !self
313 .log
314 .txn_log_get_mutable::<VariadicTypePack, TypePackId>(sub_iter.pack_id)
315 .is_null()
316 {
317 self.unifier_try_unify_variadics(
318 super_iter.pack_id,
319 sub_iter.pack_id,
320 true,
321 super_iter.index as i32,
322 );
323 } else {
324 self.try_unify_type_pack_id_type_pack_id_bool(
325 unsafe { (*sub_tpv).tail.unwrap() },
326 unsafe { (*super_tpv).tail.unwrap() },
327 false,
328 );
329 }
330 }
331
332 break;
333 }
334
335 if super_iter.weird_iter_can_grow() && sub_iter.weird_iter_can_grow() {
337 let s = unsafe { (*sub_iter.pack).tail.unwrap() };
338 let sup = unsafe { (*super_iter.pack).tail.unwrap() };
339 return self.try_unify_type_pack_id_type_pack_id_bool(s, sup, false);
340 }
341
342 if super_iter.weird_iter_can_grow() {
344 let new_tail = unsafe {
345 (*self.types).add_type_pack_type_pack_var(TypePackVar {
346 ty: TypePackVariant::TypePack(TypePack {
347 head: alloc::vec::Vec::new(),
348 tail: None,
349 }),
350 persistent: false,
351 owningArena: core::ptr::null_mut(),
352 })
353 };
354 super_iter.weird_iter_grow(new_tail);
355 } else if sub_iter.weird_iter_can_grow() {
356 let new_tail = unsafe {
357 (*self.types).add_type_pack_type_pack_var(TypePackVar {
358 ty: TypePackVariant::TypePack(TypePack {
359 head: alloc::vec::Vec::new(),
360 tail: None,
361 }),
362 persistent: false,
363 owningArena: core::ptr::null_mut(),
364 })
365 };
366 sub_iter.weird_iter_grow(new_tail);
367 } else {
368 if super_iter.weird_iter_good()
370 && is_optional(*super_iter.weird_iter_operator_deref())
371 {
372 super_iter.weird_iter_advance();
373 continue;
374 } else if sub_iter.weird_iter_good()
375 && is_optional(*sub_iter.weird_iter_operator_deref())
376 {
377 sub_iter.weird_iter_advance();
378 continue;
379 }
380
381 if !self
382 .log
383 .txn_log_get_mutable::<VariadicTypePack, TypePackId>(super_iter.pack_id)
384 .is_null()
385 {
386 self.unifier_try_unify_variadics(
387 sub_iter.pack_id,
388 super_iter.pack_id,
389 false,
390 sub_iter.index as i32,
391 );
392 return;
393 }
394
395 if !self
396 .log
397 .txn_log_get_mutable::<VariadicTypePack, TypePackId>(sub_iter.pack_id)
398 .is_null()
399 {
400 self.unifier_try_unify_variadics(
401 super_iter.pack_id,
402 sub_iter.pack_id,
403 true,
404 super_iter.index as i32,
405 );
406 return;
407 }
408
409 if !is_function_call && sub_iter.weird_iter_good() {
410 return;
412 }
413
414 let log_ptr = self.log_ptr();
416 let mut expected_size = size(super_tp, log_ptr);
417 let mut actual_size = size(sub_tp, log_ptr);
418 if self.ctx == CountMismatchContext::FunctionResult
419 || self.ctx == CountMismatchContext::ExprListResult
420 {
421 core::mem::swap(&mut expected_size, &mut actual_size);
422 }
423 let ctx = self.ctx;
424 self.report_error_location_type_error_data(
425 self.location,
426 TypeErrorData::CountMismatch(CountMismatch {
427 expected: expected_size,
428 maximum: None,
429 actual: actual_size,
430 context: ctx,
431 is_variadic: false,
432 function: String::new(),
433 }),
434 );
435
436 let error_type = unsafe { (*self.builtin_types).errorType };
437 while super_iter.weird_iter_good() {
438 let cur = *super_iter.weird_iter_operator_deref();
439 self.try_unify_type_id_type_id_bool_bool_literal_properties(
440 cur, error_type, false, false, None,
441 );
442 super_iter.weird_iter_advance();
443 }
444
445 while sub_iter.weird_iter_good() {
446 let cur = *sub_iter.weird_iter_operator_deref();
447 self.try_unify_type_id_type_id_bool_bool_literal_properties(
448 cur, error_type, false, false, None,
449 );
450 sub_iter.weird_iter_advance();
451 }
452
453 return;
454 }
455
456 if no_infinite_growth {
457 break;
458 }
459 }
460 } else {
461 self.report_error_location_type_error_data(
462 self.location,
463 TypeErrorData::TypePackMismatch(TypePackMismatch {
464 wanted_tp: super_tp,
465 given_tp: sub_tp,
466 reason: String::new(),
467 }),
468 );
469 }
470 }
471
472 fn mk_fresh_for_iter(
474 &mut self,
475 scope: *mut crate::records::scope::Scope,
476 ) -> crate::type_aliases::type_id::TypeId {
477 fresh_type(
478 unsafe { &mut *self.types },
479 unsafe { &*self.builtin_types },
480 scope,
481 Polarity::Positive,
482 )
483 }
484
485 #[inline]
486 fn log_ptr(&mut self) -> *mut crate::records::txn_log::TxnLog {
487 &mut self.log as *mut _
488 }
489}