Skip to main content

luaur_analysis/methods/
normalizer_union_of_functions.rs

1use crate::functions::get_type_alt_j::get_type_id;
2use crate::records::function_type::FunctionType;
3use crate::records::normalizer::Normalizer;
4use crate::type_aliases::error_type::ErrorType;
5use crate::type_aliases::type_id::TypeId;
6use luaur_common::macros::luau_assert::LUAU_ASSERT;
7
8impl Normalizer {
9    pub fn union_of_functions(&mut self, here: TypeId, there: TypeId) -> Option<TypeId> {
10        self.consume_fuel();
11
12        unsafe {
13            if !get_type_id::<ErrorType>(here).is_null() {
14                return Some(here);
15            }
16
17            if !get_type_id::<ErrorType>(there).is_null() {
18                return Some(there);
19            }
20
21            let hftv = get_type_id::<FunctionType>(here);
22            LUAU_ASSERT!(!hftv.is_null());
23            let tftv = get_type_id::<FunctionType>(there);
24            LUAU_ASSERT!(!tftv.is_null());
25
26            let h_generics = (*hftv).generics.clone();
27            let t_generics = (*tftv).generics.clone();
28            if h_generics != t_generics {
29                return None;
30            }
31
32            let h_generic_packs = (*hftv).generic_packs.clone();
33            let t_generic_packs = (*tftv).generic_packs.clone();
34            if h_generic_packs != t_generic_packs {
35                return None;
36            }
37
38            let arg_types =
39                self.intersection_of_type_packs_internal((*hftv).arg_types, (*tftv).arg_types);
40            if arg_types.is_none() {
41                return None;
42            }
43
44            let ret_types = self.union_of_type_packs((*hftv).ret_types, (*tftv).ret_types);
45            if ret_types.is_none() {
46                return None;
47            }
48
49            let arg_types_val = arg_types.unwrap();
50            let ret_types_val = ret_types.unwrap();
51
52            if arg_types_val == (*hftv).arg_types && ret_types_val == (*hftv).ret_types {
53                return Some(here);
54            }
55
56            if arg_types_val == (*tftv).arg_types && ret_types_val == (*tftv).ret_types {
57                return Some(there);
58            }
59
60            let mut result =
61                FunctionType::function_type_new(arg_types_val, ret_types_val, None, false);
62            result.generics = h_generics;
63            result.generic_packs = h_generic_packs;
64
65            Some((*self.arena).add_type(result))
66        }
67    }
68}