luaur_analysis/methods/
subtyping_unifier_occurs_check_deprecated.rs1use crate::enums::occurs_check_result::OccursCheckResult;
2use crate::functions::follow_type_pack::follow_type_pack_id;
3use crate::records::error_type_pack::ErrorTypePack;
4use crate::records::free_type_pack::FreeTypePack;
5use crate::records::subtyping_unifier::SubtypingUnifier;
6use crate::records::type_pack::TypePack;
7use crate::type_aliases::error_type_pack::ErrorTypePack as ErrorTypePackAlias;
8use crate::type_aliases::free_type_pack::FreeTypePack as FreeTypePackAlias;
9use crate::type_aliases::type_pack_id::TypePackId;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12impl SubtypingUnifier {
13 pub fn occurs_check_deprecated(
14 &self,
15 needle: TypePackId,
16 haystack: TypePackId,
17 ) -> OccursCheckResult {
18 let needle_followed = unsafe { follow_type_pack_id(needle) };
19 let haystack_followed = unsafe { follow_type_pack_id(haystack) };
20
21 if !unsafe {
22 crate::functions::get_mutable_type_pack::get_mutable_type_pack_id::<ErrorTypePackAlias>(
23 needle_followed,
24 )
25 }
26 .is_null()
27 {
28 return OccursCheckResult::Pass;
29 }
30
31 if unsafe {
32 crate::functions::get_mutable_type_pack::get_mutable_type_pack_id::<FreeTypePackAlias>(
33 needle_followed,
34 )
35 }
36 .is_null()
37 {
38 LUAU_ASSERT!(false, "Expected needle pack to be free");
39 }
40
41 let mut current_haystack = haystack_followed;
42 while unsafe {
43 crate::functions::get_mutable_type_pack::get_mutable_type_pack_id::<ErrorTypePackAlias>(
44 current_haystack,
45 )
46 }
47 .is_null()
48 {
49 if needle_followed == current_haystack {
50 return OccursCheckResult::Fail;
51 }
52
53 let pack_ptr = unsafe {
54 crate::functions::get_type_pack::get_type_pack_id::<TypePack>(current_haystack)
55 };
56 if !pack_ptr.is_null() {
57 let tail_opt = unsafe { (*pack_ptr).tail };
58 if let Some(tail) = tail_opt {
59 current_haystack = unsafe { follow_type_pack_id(tail) };
60 continue;
61 }
62 }
63
64 break;
65 }
66
67 OccursCheckResult::Pass
68 }
69}