luaur_analysis/methods/
normalizer_negate_normal.rs1use crate::functions::get_singleton_type::get_singleton_type;
2use crate::functions::get_type_alt_j::get_type_id;
3use crate::functions::is_top::is_top;
4use crate::functions::reset_to_top::reset_to_top;
5use crate::records::boolean_singleton::BooleanSingleton;
6use crate::records::never_type::NeverType;
7use crate::records::normalized_extern_type::NormalizedExternType;
8use crate::records::normalized_function_type::NormalizedFunctionType;
9use crate::records::normalized_string_type::NormalizedStringType;
10use crate::records::normalized_type::NormalizedType;
11use crate::records::normalizer::Normalizer;
12use crate::records::primitive_type::PrimitiveType;
13use crate::records::singleton_type::SingletonType;
14use crate::records::type_ids::TypeIds;
15use alloc::collections::BTreeMap;
16use luaur_common::macros::luau_assert::LUAU_ASSERT;
17use luaur_common::FFlag;
18
19impl Normalizer {
20 pub fn negate_normal(&mut self, here: &NormalizedType) -> Option<NormalizedType> {
21 self.consume_fuel();
22
23 let never_type = unsafe { (*here.builtin_types).neverType };
24 let mut result = NormalizedType {
25 builtin_types: here.builtin_types,
26 tops: never_type,
27 booleans: never_type,
28 extern_types: NormalizedExternType {
29 extern_types: BTreeMap::new(),
30 shape_extensions: TypeIds::type_ids(),
31 ordering: Vec::new(),
32 },
33 errors: never_type,
34 nils: never_type,
35 numbers: never_type,
36 integers: never_type,
37 strings: NormalizedStringType::never,
38 threads: never_type,
39 buffers: never_type,
40 tables: TypeIds::type_ids(),
41 functions: NormalizedFunctionType {
42 is_top: false,
43 parts: TypeIds::type_ids(),
44 },
45 tyvars: BTreeMap::new(),
46 is_cacheable: true,
47 };
48 result.is_cacheable = here.is_cacheable;
49
50 let here_tops = unsafe { get_type_id::<NeverType>(here.tops) };
51 if here_tops.is_null() {
52 return Some(result);
53 }
54
55 let here_errors = unsafe { get_type_id::<NeverType>(here.errors) };
56 if here_errors.is_null() {
57 result.errors = here.errors;
58 return Some(result);
59 }
60
61 let here_booleans = here.booleans;
62 let here_booleans_tv = unsafe { get_type_id::<NeverType>(here_booleans) };
63 if !here_booleans_tv.is_null() {
64 result.booleans = unsafe { (*here.builtin_types).booleanType };
65 } else {
66 let here_booleans_tv = unsafe { get_type_id::<PrimitiveType>(here_booleans) };
67 if !here_booleans_tv.is_null() {
68 result.booleans = unsafe { (*here.builtin_types).neverType };
69 } else {
70 let here_booleans_tv = unsafe { get_type_id::<SingletonType>(here_booleans) };
71 if !here_booleans_tv.is_null() {
72 let boolean = get_singleton_type::<BooleanSingleton>(here_booleans_tv);
73 LUAU_ASSERT!(!boolean.is_null());
74 if unsafe { &*boolean }.value {
75 result.booleans = unsafe { (*here.builtin_types).falseType };
76 } else {
77 result.booleans = unsafe { (*here.builtin_types).trueType };
78 }
79 }
80 }
81 }
82
83 let extern_types = &here.extern_types;
84 if extern_types.is_never() {
85 reset_to_top(unsafe { &*here.builtin_types }, &mut result.extern_types);
86 } else if is_top(unsafe { &*here.builtin_types }, extern_types) {
87 result.extern_types.reset_to_never();
88 } else {
89 let mut root_negations = TypeIds::type_ids();
90
91 for (here_parent, here_negations) in &extern_types.extern_types {
92 if *here_parent != unsafe { (*here.builtin_types).externType } {
93 root_negations.insert_type_id(*here_parent);
94 }
95
96 for &here_negation in &here_negations.order {
97 self.union_extern_types_with_extern_type_normalized_extern_type_type_id(
98 &mut result.extern_types,
99 here_negation,
100 );
101 }
102 }
103
104 if !root_negations.empty() {
105 result
106 .extern_types
107 .push_pair(unsafe { (*here.builtin_types).externType }, root_negations);
108 }
109 }
110
111 let here_nils = unsafe { get_type_id::<NeverType>(here.nils) };
112 if !here_nils.is_null() {
113 result.nils = unsafe { (*here.builtin_types).nilType };
114 } else {
115 result.nils = unsafe { (*here.builtin_types).neverType };
116 }
117
118 let here_numbers = unsafe { get_type_id::<NeverType>(here.numbers) };
119 if !here_numbers.is_null() {
120 result.numbers = unsafe { (*here.builtin_types).numberType };
121 } else {
122 result.numbers = unsafe { (*here.builtin_types).neverType };
123 }
124
125 if FFlag::LuauIntegerType2.get() {
126 let here_integers = unsafe { get_type_id::<NeverType>(here.integers) };
127 if !here_integers.is_null() {
128 result.integers = unsafe { (*here.builtin_types).integerType };
129 } else {
130 result.integers = unsafe { (*here.builtin_types).neverType };
131 }
132 }
133
134 result.strings = here.strings.clone();
135 result.strings.isCofinite = !result.strings.isCofinite;
136
137 let here_threads = unsafe { get_type_id::<NeverType>(here.threads) };
138 if !here_threads.is_null() {
139 result.threads = unsafe { (*here.builtin_types).threadType };
140 } else {
141 result.threads = unsafe { (*here.builtin_types).neverType };
142 }
143
144 let here_buffers = unsafe { get_type_id::<NeverType>(here.buffers) };
145 if !here_buffers.is_null() {
146 result.buffers = unsafe { (*here.builtin_types).bufferType };
147 } else {
148 result.buffers = unsafe { (*here.builtin_types).neverType };
149 }
150
151 if here.functions.is_never() {
152 result.functions.reset_to_top();
153 } else if here.functions.is_top {
154 result.functions.reset_to_never();
155 } else {
156 return None;
157 }
158
159 if here.tables.empty() {
160 result
161 .tables
162 .insert_type_id(unsafe { (*here.builtin_types).tableType });
163 } else if here.tables.size() == 1
164 && here.tables.front() == unsafe { (*here.builtin_types).tableType }
165 {
166 result.tables.clear();
167 } else {
168 return None;
169 }
170
171 Some(result)
172 }
173}