luaur_analysis/methods/
overload_resolver_test_function.rs1use crate::enums::type_function_instance_state::TypeFunctionInstanceState;
6use crate::functions::are_unsatisfied_arguments_optional::are_unsatisfied_arguments_optional;
7use crate::functions::follow_type::follow_type_id;
8use crate::functions::get_type_alt_j::get_type_id;
9use crate::functions::ignore_reasoning_for_return_type::ignore_reasoning_for_return_type;
10use crate::functions::reduce_type_functions_type_function::reduce_type_functions;
11use crate::records::blocked_type::BlockedType;
12use crate::records::free_type::FreeType;
13use crate::records::function_type::FunctionType;
14use crate::records::overload_resolution::OverloadResolution;
15use crate::records::overload_resolver::OverloadResolver;
16use crate::records::pending_expansion_type::PendingExpansionType;
17use crate::records::type_error::TypeError;
18use crate::records::type_function_context::TypeFunctionContext;
19use crate::records::type_function_instance_type::TypeFunctionInstanceType;
20use crate::type_aliases::error_vec::ErrorVec;
21use crate::type_aliases::type_id::TypeId;
22use crate::type_aliases::type_pack_id::TypePackId;
23use core::ptr::NonNull;
24use luaur_ast::records::location::Location;
25use luaur_common::records::dense_hash_set::DenseHashSet;
26use luaur_common::records::variant::Variant2;
27
28impl OverloadResolver {
29 pub fn test_function(
30 &mut self,
31 result: &mut OverloadResolution,
32 fn_ty: TypeId,
33 args_pack: TypePackId,
34 fn_location: Location,
35 unique_types: *mut DenseHashSet<TypeId>,
36 ) {
37 let fn_ty = unsafe { follow_type_id(fn_ty) };
38
39 if unsafe {
41 !get_type_id::<FreeType>(fn_ty).is_null()
42 || !get_type_id::<BlockedType>(fn_ty).is_null()
43 || !get_type_id::<PendingExpansionType>(fn_ty).is_null()
44 } {
45 let constraints = alloc::vec::Vec::new();
47 result.potential_overloads.push((fn_ty, constraints));
48 return;
49 }
50
51 let tfit = unsafe { get_type_id::<TypeFunctionInstanceType>(fn_ty) };
52 if !tfit.is_null() && unsafe { (*tfit).state } == TypeFunctionInstanceState::Unsolved {
53 let constraints = alloc::vec::Vec::new();
55 result.potential_overloads.push((fn_ty, constraints));
56 return;
57 }
58
59 let ftv = unsafe { get_type_id::<FunctionType>(fn_ty) };
60 if ftv.is_null() {
61 result.non_functions.push(fn_ty);
62 return;
63 }
64 let ftv = unsafe { &*ftv };
65
66 if !self.is_arity_compatible(args_pack, ftv.arg_types, self.builtin_types) {
67 result.arity_mismatches.push(fn_ty);
68 return;
69 }
70
71 let context = TypeFunctionContext {
72 arena: unsafe { NonNull::new_unchecked(self.arena) },
73 builtins: unsafe { NonNull::new_unchecked(self.builtin_types) },
74 scope: unsafe { NonNull::new_unchecked(self.scope) },
75 normalizer: unsafe { NonNull::new_unchecked(self.normalizer) },
76 type_function_runtime: unsafe { NonNull::new_unchecked(self.type_function_runtime) },
77 ice: unsafe { NonNull::new_unchecked(self.ice) },
78 limits: unsafe { NonNull::new_unchecked(&self.limits as *const _ as *mut _) },
79 subtyping: unsafe { NonNull::new_unchecked(&mut self.subtyping as *mut _) },
80 solver: core::ptr::null_mut(),
81 constraint: core::ptr::null(),
82 user_func_name: None,
83 fresh_instances: alloc::vec::Vec::new(),
84 };
85 let mut context = context;
86 let reduce_result = reduce_type_functions(
87 fn_ty,
88 self.call_loc,
89 unsafe { NonNull::new_unchecked(&mut context as *mut _) },
90 true,
91 );
92 if !reduce_result.errors.is_empty() {
93 result
94 .incompatible_overloads
95 .push((fn_ty, Variant2::V1(reduce_result.errors)));
96 return;
97 }
98
99 let prospective_function = unsafe {
100 (*self.arena).add_type(FunctionType::function_type_new(
101 args_pack,
102 (*self.builtin_types).anyTypePack,
103 None,
104 false,
105 ))
106 };
107
108 self.subtyping.unique_types = unique_types as *const DenseHashSet<TypeId>;
109 let scope = self.scope;
110 let mut r = self.subtyping.is_subtype_type_id_type_id_not_null_scope(
111 fn_ty,
112 prospective_function,
113 scope,
114 );
115
116 ignore_reasoning_for_return_type(&mut r);
121
122 if r.is_subtype {
123 if r.assumed_constraints.is_empty() {
124 result.ok.push(fn_ty);
125 } else {
126 result
127 .potential_overloads
128 .push((fn_ty, core::mem::take(&mut r.assumed_constraints)));
129 }
130 } else if !r.generic_bounds_mismatches.is_empty() {
131 let mut errors: ErrorVec = alloc::vec::Vec::new();
132 for gbm in r.generic_bounds_mismatches.iter() {
133 errors.push(TypeError::type_error_location_type_error_data(
134 fn_location,
135 crate::type_aliases::type_error_data::TypeErrorData::GenericBoundsMismatch(
136 gbm.clone(),
137 ),
138 ));
139 }
140 result
141 .incompatible_overloads
142 .push((fn_ty, Variant2::V1(errors)));
143 } else if are_unsatisfied_arguments_optional(&r.reasoning, args_pack, ftv.arg_types) {
144 if r.assumed_constraints.is_empty() {
149 result.ok.push(fn_ty);
150 } else {
151 result
152 .potential_overloads
153 .push((fn_ty, core::mem::take(&mut r.assumed_constraints)));
154 }
155 } else {
156 result
157 .incompatible_overloads
158 .push((fn_ty, Variant2::V0(core::mem::take(&mut r.reasoning))));
159 }
160 }
161}