Skip to main content

luaur_analysis/methods/
normalizer_subtract_singleton.rs

1use crate::functions::get_type_alt_j::get_type_id;
2use crate::records::boolean_singleton::BooleanSingleton;
3use crate::records::never_type::NeverType;
4use crate::records::normalized_type::NormalizedType;
5use crate::records::normalizer::Normalizer;
6use crate::records::primitive_type::PrimitiveType;
7use crate::records::singleton_type::SingletonType;
8use crate::records::string_singleton::StringSingleton;
9use crate::type_aliases::type_id::TypeId;
10use luaur_common::macros::luau_assert::LUAU_ASSERT;
11
12impl Normalizer {
13    pub fn subtract_singleton(&mut self, here: &mut NormalizedType, ty: TypeId) {
14        self.consume_fuel();
15
16        let stv = unsafe { get_type_id::<SingletonType>(ty) };
17        LUAU_ASSERT!(!stv.is_null());
18
19        let stv = unsafe { &*stv };
20
21        if let Some(ss) = stv.variant.get_if::<StringSingleton>() {
22            if here.strings.isCofinite {
23                here.strings.singletons.insert(ss.value.clone(), ty);
24            } else {
25                let it = here.strings.singletons.get_mut(&ss.value);
26                if let Some(_) = it {
27                    here.strings.singletons.remove(&ss.value);
28                }
29            }
30        } else if let Some(bs) = stv.variant.get_if::<BooleanSingleton>() {
31            if !unsafe { get_type_id::<NeverType>(here.booleans).is_null() } {
32                // Nothing
33            } else if !unsafe { get_type_id::<PrimitiveType>(here.booleans).is_null() } {
34                let prim = unsafe { &*get_type_id::<PrimitiveType>(here.booleans) };
35                if prim.r#type == PrimitiveType::Boolean {
36                    here.booleans = if bs.value {
37                        unsafe { (*self.builtin_types).falseType }
38                    } else {
39                        unsafe { (*self.builtin_types).trueType }
40                    };
41                }
42            } else if let Some(here_singleton) = unsafe {
43                get_type_id::<SingletonType>(here.booleans)
44                    .as_ref()
45                    .and_then(|s| s.variant.get_if::<BooleanSingleton>())
46            } {
47                // Crucial subtlety: ty (and thus bs) are the value that is being
48                // negated out. We therefore reduce to never when the values match,
49                // rather than when they differ.
50                if bs.value == here_singleton.value {
51                    here.booleans = unsafe { (*self.builtin_types).neverType };
52                }
53            } else {
54                LUAU_ASSERT!(false);
55            }
56        } else {
57            LUAU_ASSERT!(false);
58        }
59    }
60}