Skip to main content

luaur_analysis/methods/
unifier_try_apply_overloaded_function.rs

1//! Source: `Analysis/src/Unifier.cpp` (Unifier::tryApplyOverloadedFunction, L1161-1224)
2use crate::functions::get_type_alt_j::get_type_id;
3use crate::functions::has_unification_too_complex::has_unification_too_complex;
4use crate::records::cannot_call_non_function::CannotCallNonFunction;
5use crate::records::function_type::FunctionType;
6use crate::records::generic_error::GenericError;
7use crate::records::normalized_function_type::NormalizedFunctionType;
8use crate::records::unifier::Unifier;
9use crate::type_aliases::type_error_data::TypeErrorData;
10use crate::type_aliases::type_id::TypeId;
11use crate::type_aliases::type_pack_id::TypePackId;
12use alloc::string::String;
13
14impl Unifier {
15    /// `TypePackId Unifier::tryApplyOverloadedFunction(TypeId function, const NormalizedFunctionType& overloads, TypePackId args)`
16    pub fn unifier_try_apply_overloaded_function(
17        &mut self,
18        function: TypeId,
19        overloads: &NormalizedFunctionType,
20        args: TypePackId,
21    ) -> TypePackId {
22        if overloads.is_never() {
23            self.report_error_location_type_error_data(
24                self.location,
25                TypeErrorData::CannotCallNonFunction(CannotCallNonFunction { ty: function }),
26            );
27            return unsafe { (*self.builtin_types).errorTypePack };
28        }
29
30        let mut result: Option<TypePackId> = None;
31        let mut first_fun: *const FunctionType = core::ptr::null();
32
33        let parts = overloads.parts.order.clone();
34        for overload in parts {
35            let ftv = unsafe { get_type_id::<FunctionType>(overload) };
36            if !ftv.is_null() {
37                // TODO: instantiate generics?
38                if unsafe { (*ftv).generics.is_empty() && (*ftv).generic_packs.is_empty() } {
39                    if first_fun.is_null() {
40                        first_fun = ftv;
41                    }
42                    let mut inner_state = self.unifier_make_child_unifier();
43                    inner_state.try_unify_type_pack_id_type_pack_id_bool(
44                        args,
45                        unsafe { (*ftv).arg_types },
46                        false,
47                    );
48                    if inner_state.errors.is_empty() {
49                        self.log.concat(inner_state.log.clone());
50                        if let Some(res) = result {
51                            inner_state.log.clear();
52                            inner_state.try_unify_type_pack_id_type_pack_id_bool(
53                                res,
54                                unsafe { (*ftv).ret_types },
55                                false,
56                            );
57                            if inner_state.errors.is_empty() {
58                                self.log.concat(inner_state.log.clone());
59                            }
60                            // Annoyingly, since we don't support intersection of generic type packs,
61                            // the intersection may fail. We rather arbitrarily use the first matching overload
62                            // in that case.
63                            else if let Some(intersect) = unsafe {
64                                (*self.normalizer).intersection_of_type_packs(res, (*ftv).ret_types)
65                            } {
66                                result = Some(intersect);
67                            }
68                        } else {
69                            result = Some(unsafe { (*ftv).ret_types });
70                        }
71                    } else if let Some(e) = has_unification_too_complex(&inner_state.errors) {
72                        self.report_error_type_error(e);
73                        return unsafe { (*self.builtin_types).error_recovery_type_pack(args) };
74                    }
75                }
76            }
77        }
78
79        if let Some(res) = result {
80            res
81        } else if !first_fun.is_null() {
82            // TODO: better error reporting?
83            // The logic for error reporting overload resolution
84            // is currently over in TypeInfer.cpp, should we move it?
85            self.report_error_location_type_error_data(
86                self.location,
87                TypeErrorData::GenericError(GenericError::new(String::from(
88                    "No matching overload.",
89                ))),
90            );
91            unsafe { (*self.builtin_types).error_recovery_type_pack((*first_fun).ret_types) }
92        } else {
93            self.report_error_location_type_error_data(
94                self.location,
95                TypeErrorData::CannotCallNonFunction(CannotCallNonFunction { ty: function }),
96            );
97            unsafe { (*self.builtin_types).errorTypePack }
98        }
99    }
100}