luaur_analysis/functions/
is_cacheable_normalize_alt_b.rs1use 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}