Skip to main content

luaur_analysis/functions/
has_length.rs

1use crate::functions::follow_type::follow_type_id;
2use crate::functions::get_type_alt_j::get_type_id;
3use crate::functions::is_prim::is_prim;
4use crate::functions::is_string::is_string;
5use crate::records::any_type::AnyType;
6use crate::records::intersection_type::IntersectionType;
7use crate::records::metatable_type::MetatableType;
8use crate::records::primitive_type::PrimitiveType;
9use crate::records::recursion_limiter::RecursionLimiter;
10use crate::records::table_type::TableType;
11use crate::records::union_type::UnionType;
12use crate::type_aliases::type_id::TypeId;
13use luaur_common::records::dense_hash_set::DenseHashSet;
14use luaur_common::FInt;
15
16pub fn has_length(ty: TypeId, seen: &mut DenseHashSet<TypeId>, recursion_count: &mut i32) -> bool {
17    let mut _rl = RecursionLimiter {
18        base: unsafe { core::mem::zeroed() },
19        native_stack_guard: unsafe { core::mem::zeroed() },
20    };
21    _rl.recursion_limiter_recursion_limiter(
22        "Type::hasLength",
23        recursion_count as *mut i32 as *mut core::ffi::c_int,
24        FInt::LuauTypeInferRecursionLimit.get() as core::ffi::c_int,
25    );
26
27    let ty = unsafe { follow_type_id(ty) };
28
29    if seen.contains(&ty) {
30        return true;
31    }
32
33    unsafe {
34        if is_string(ty)
35            || is_prim(ty, PrimitiveType::Table)
36            || !get_type_id::<AnyType>(ty).is_null()
37            || !get_type_id::<TableType>(ty).is_null()
38            || !get_type_id::<MetatableType>(ty).is_null()
39        {
40            return true;
41        }
42
43        let uty = get_type_id::<UnionType>(ty);
44        if !uty.is_null() {
45            seen.insert(ty);
46
47            for &part in &(*uty).options {
48                if !has_length(part, seen, recursion_count) {
49                    return false;
50                }
51            }
52
53            return true;
54        }
55
56        let ity = get_type_id::<IntersectionType>(ty);
57        if !ity.is_null() {
58            seen.insert(ty);
59
60            for &part in &(*ity).parts {
61                if has_length(part, seen, recursion_count) {
62                    return true;
63                }
64            }
65
66            return false;
67        }
68    }
69
70    false
71}