Skip to main content

luaur_analysis/functions/
is_cacheable_normalize_alt_b.rs

1//! Source: `Analysis/src/Normalize.cpp:875-923` (hand-ported)
2//!
3//! Two `isCacheable` overloads from Normalize.cpp:
4//!   * `isCacheable(TypePackId, Set<TypeId>&)`  (Normalize.cpp:875-894)
5//!   * `isCacheable(TypeId, Set<TypeId>&)`       (Normalize.cpp:896-923)
6use crate::functions::begin_type_pack::begin_type_pack_id;
7use crate::functions::end_type_pack::end;
8use crate::functions::follow_type::follow_type_id;
9use crate::functions::get_type_alt_j::get_type_id;
10use crate::functions::get_type_pack::get_type_pack_id;
11use crate::records::blocked_type::BlockedType;
12use crate::records::blocked_type_pack::BlockedTypePack;
13use crate::records::free_type::FreeType;
14use crate::records::free_type_pack::FreeTypePack;
15use crate::records::pending_expansion_type::PendingExpansionType;
16use crate::records::type_function_instance_type::TypeFunctionInstanceType;
17use crate::records::type_function_instance_type_pack::TypeFunctionInstanceTypePack;
18use crate::type_aliases::type_id::TypeId;
19use crate::type_aliases::type_pack_id::TypePackId;
20use luaur_common::records::dense_hash_set::DenseHashSet;
21
22pub fn is_cacheable_type_pack_id_set_type_id(
23    tp: TypePackId,
24    seen: &mut DenseHashSet<TypeId>,
25) -> bool {
26    let tp = unsafe { crate::functions::follow_type_pack::follow_type_pack_id(tp) };
27
28    unsafe {
29        let mut it = begin_type_pack_id(tp);
30        let end_it = end(tp);
31
32        while it.operator_ne(&end_it) {
33            if !is_cacheable(*it.operator_deref(), seen) {
34                return false;
35            }
36            it.operator_inc();
37        }
38
39        if let Some(tail) = it.tail() {
40            if !get_type_pack_id::<FreeTypePack>(tail).is_null()
41                || !get_type_pack_id::<BlockedTypePack>(tail).is_null()
42                || !get_type_pack_id::<TypeFunctionInstanceTypePack>(tail).is_null()
43            {
44                return false;
45            }
46        }
47    }
48
49    true
50}
51
52pub fn is_cacheable(ty: TypeId, seen: &mut DenseHashSet<TypeId>) -> bool {
53    if seen.contains(&ty) {
54        return true;
55    }
56    seen.insert(ty);
57
58    let ty = unsafe { follow_type_id(ty) };
59
60    if !unsafe { get_type_id::<FreeType>(ty).is_null() }
61        || !unsafe { get_type_id::<BlockedType>(ty).is_null() }
62        || !unsafe { get_type_id::<PendingExpansionType>(ty).is_null() }
63    {
64        return false;
65    }
66
67    if let Some(tfi) = unsafe { get_type_id::<TypeFunctionInstanceType>(ty).as_ref() } {
68        for t in &tfi.type_arguments {
69            if !is_cacheable(*t, seen) {
70                return false;
71            }
72        }
73        for tp in &tfi.pack_arguments {
74            if !is_cacheable_type_pack_id_set_type_id(*tp, seen) {
75                return false;
76            }
77        }
78    }
79
80    true
81}