Skip to main content

luaur_analysis/methods/
subtyping_unifier_occurs_check_deprecated.rs

1use 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}