Skip to main content

luaur_analysis/methods/
normalizer_union_normals.rs

1use crate::enums::normalization_result::NormalizationResult;
2use crate::functions::get_type_alt_j::get_type_id;
3use crate::functions::tyvar_index::tyvar_index;
4use crate::records::never_type::NeverType;
5use crate::records::normalized_extern_type::NormalizedExternType;
6use crate::records::normalized_function_type::NormalizedFunctionType;
7use crate::records::normalized_string_type::NormalizedStringType;
8use crate::records::normalized_type::NormalizedType;
9use crate::records::normalizer::Normalizer;
10use crate::records::type_ids::TypeIds;
11use crate::records::unknown_type::UnknownType;
12use crate::type_aliases::error_type::ErrorType;
13use alloc::collections::BTreeMap;
14use luaur_common::FFlag;
15
16impl Normalizer {
17    pub fn union_normals(
18        &mut self,
19        here: &mut NormalizedType,
20        there: &NormalizedType,
21        ignore_smaller_tyvars: i32,
22    ) -> NormalizationResult {
23        self.consume_fuel();
24
25        here.is_cacheable &= there.is_cacheable;
26
27        let mut tops = self.union_of_tops(here.tops, there.tops);
28        if !unsafe { get_type_id::<UnknownType>(tops).is_null() }
29            && (!unsafe { get_type_id::<ErrorType>(here.errors).is_null() }
30                || !unsafe { get_type_id::<ErrorType>(there.errors).is_null() })
31        {
32            tops = unsafe { (*here.builtin_types).anyType };
33        }
34
35        if unsafe { get_type_id::<NeverType>(tops).is_null() } {
36            self.clear_normal(here);
37            here.tops = tops;
38            return NormalizationResult::True;
39        }
40
41        for (tyvar, inter_box) in &there.tyvars {
42            let index = tyvar_index(*tyvar);
43            if index <= ignore_smaller_tyvars {
44                continue;
45            }
46
47            if !here.tyvars.contains_key(tyvar) {
48                let never_type = unsafe { (*here.builtin_types).neverType };
49                let mut fresh = NormalizedType {
50                    builtin_types: here.builtin_types,
51                    tops: never_type,
52                    booleans: never_type,
53                    extern_types: NormalizedExternType {
54                        extern_types: BTreeMap::new(),
55                        shape_extensions: TypeIds::type_ids(),
56                        ordering: Vec::new(),
57                    },
58                    errors: never_type,
59                    nils: never_type,
60                    numbers: never_type,
61                    integers: never_type,
62                    strings: NormalizedStringType::never,
63                    threads: never_type,
64                    buffers: never_type,
65                    tables: TypeIds::type_ids(),
66                    functions: NormalizedFunctionType {
67                        is_top: false,
68                        parts: TypeIds::type_ids(),
69                    },
70                    tyvars: BTreeMap::new(),
71                    is_cacheable: true,
72                };
73                let res = self.union_normals(&mut fresh, here, index);
74                if res != NormalizationResult::True {
75                    return res;
76                }
77                here.tyvars.insert(*tyvar, Box::new(fresh));
78            }
79
80            if let Some(mut current) = here.tyvars.remove(tyvar) {
81                let res = self.union_normals(&mut current, inter_box, index);
82                if res != NormalizationResult::True {
83                    return res;
84                }
85                here.tyvars.insert(*tyvar, current);
86            }
87        }
88
89        here.booleans = self.union_of_bools(here.booleans, there.booleans);
90        self.union_extern_types_normalized_extern_type_normalized_extern_type(
91            &mut here.extern_types,
92            &there.extern_types,
93        );
94
95        here.errors = if !unsafe { get_type_id::<NeverType>(there.errors).is_null() } {
96            here.errors
97        } else {
98            there.errors
99        };
100        here.nils = if !unsafe { get_type_id::<NeverType>(there.nils).is_null() } {
101            here.nils
102        } else {
103            there.nils
104        };
105        here.numbers = if !unsafe { get_type_id::<NeverType>(there.numbers).is_null() } {
106            here.numbers
107        } else {
108            there.numbers
109        };
110        if FFlag::LuauIntegerType2.get() {
111            here.integers = if !unsafe { get_type_id::<NeverType>(there.integers).is_null() } {
112                here.integers
113            } else {
114                there.integers
115            };
116        }
117        self.union_strings(&mut here.strings, &there.strings);
118        here.threads = if !unsafe { get_type_id::<NeverType>(there.threads).is_null() } {
119            here.threads
120        } else {
121            there.threads
122        };
123        here.buffers = if !unsafe { get_type_id::<NeverType>(there.buffers).is_null() } {
124            here.buffers
125        } else {
126            there.buffers
127        };
128        self.union_functions(&mut here.functions, &there.functions);
129        self.union_tables(&mut here.tables, &there.tables);
130
131        NormalizationResult::True
132    }
133}