luaur_analysis/methods/
normalizer_is_inhabited_normalize_alt_d.rs1use crate::enums::normalization_result::NormalizationResult;
2use crate::functions::follow_type::follow_type_id;
3use crate::functions::get_type_alt_j::get_type_id;
4use crate::records::intersection_type::IntersectionType;
5use crate::records::metatable_type::MetatableType;
6use crate::records::never_type::NeverType;
7use crate::records::normalizer::Normalizer;
8use crate::records::table_type::TableType;
9use crate::records::union_type::UnionType;
10use crate::type_aliases::type_id::TypeId;
11use luaur_common::records::dense_hash_set::DenseHashSet;
12
13struct RecursionCountGuard {
14 count: *mut i32,
15}
16
17impl RecursionCountGuard {
18 fn new(count: *mut i32) -> Self {
19 unsafe {
20 *count += 1;
21 }
22 Self { count }
23 }
24}
25
26impl Drop for RecursionCountGuard {
27 fn drop(&mut self) {
28 unsafe {
29 debug_assert!(*self.count > 0);
30 *self.count -= 1;
31 }
32 }
33}
34
35impl Normalizer {
36 pub fn is_inhabited_type_id_set_type_id(
37 &mut self,
38 ty: TypeId,
39 seen: &mut DenseHashSet<TypeId>,
40 ) -> NormalizationResult {
41 let _rc =
42 RecursionCountGuard::new(unsafe { &mut (*self.shared_state).counters.recursion_count });
43
44 if !self.within_resource_limits() {
45 return NormalizationResult::HitLimits;
46 }
47
48 self.consume_fuel();
49
50 let ty = unsafe { follow_type_id(ty) };
51
52 if !unsafe { get_type_id::<NeverType>(ty).is_null() } {
53 return NormalizationResult::False;
54 }
55
56 if unsafe { get_type_id::<IntersectionType>(ty).is_null() }
57 && unsafe { get_type_id::<UnionType>(ty).is_null() }
58 && unsafe { get_type_id::<TableType>(ty).is_null() }
59 && unsafe { get_type_id::<MetatableType>(ty).is_null() }
60 {
61 return NormalizationResult::True;
62 }
63
64 if seen.contains(&ty) {
65 return NormalizationResult::True;
66 }
67
68 seen.insert(ty);
69
70 if let Some(ttv) = unsafe { get_type_id::<TableType>(ty).as_ref() } {
71 for (_k, prop) in &ttv.props {
72 if self.use_new_luau_solver() {
73 if let Some(ty) = prop.read_ty {
74 let res = self.is_inhabited_type_id_set_type_id(ty, seen);
75 if res != NormalizationResult::True {
76 return res;
77 }
78 }
79 } else {
80 let res = self.is_inhabited_type_id_set_type_id(prop.read_ty.unwrap(), seen);
81 if res != NormalizationResult::True {
82 return res;
83 }
84 }
85 }
86 return NormalizationResult::True;
87 }
88
89 if let Some(mtv) = unsafe { get_type_id::<MetatableType>(ty).as_ref() } {
90 let res = self.is_inhabited_type_id_set_type_id(mtv.table, seen);
91 if res != NormalizationResult::True {
92 return res;
93 }
94 return self.is_inhabited_type_id_set_type_id(mtv.metatable, seen);
95 }
96
97 let norm = self.normalize(ty);
98 self.is_inhabited_normalized_type_set_type_id(norm.as_ref(), seen)
99 }
100}