luaur_analysis/functions/
solve_function_call.rs1use crate::enums::polarity::Polarity;
7use crate::enums::unify_result::UnifyResult;
8use crate::functions::get_approximate_return_type_for_function_call_type_utils::get_approximate_return_type_for_function_call_type_id_dense_hash_set_type_id as get_approximate_return_type_for_function_call;
9use crate::functions::instantiate_2_instantiation_2_alt_b::instantiate_2;
10use crate::functions::track_interior_free_type::track_interior_free_type;
11use crate::functions::track_interior_free_type_pack::track_interior_free_type_pack;
12use crate::records::function_type::FunctionType;
13use crate::records::overload_resolution::OverloadResolution;
14use crate::records::overload_resolver::OverloadResolver;
15use crate::records::subtyping::Subtyping;
16use crate::records::type_function_context::TypeFunctionContext;
17use crate::records::unifier_2::Unifier2;
18use crate::type_aliases::type_id::TypeId;
19use crate::type_aliases::type_pack_id::TypePackId;
20use luaur_ast::records::location::Location;
21use luaur_common::records::dense_hash_set::DenseHashSet;
22
23pub fn solve_function_call(
24 ctx: *mut TypeFunctionContext,
25 location: Location,
26 fn_ty: TypeId,
27 args_pack: TypePackId,
28) -> Option<TypePackId> {
29 let ctx_ref = unsafe { &*ctx };
30
31 let subtyping = Subtyping::subtyping_owned(
35 ctx_ref.builtins.as_ptr(),
36 ctx_ref.arena.as_ptr(),
37 ctx_ref.normalizer.as_ptr(),
38 ctx_ref.type_function_runtime.as_ptr(),
39 ctx_ref.ice.as_ptr(),
40 );
41 let mut resolver = OverloadResolver {
42 builtin_types: ctx_ref.builtins.as_ptr(),
43 arena: ctx_ref.arena.as_ptr(),
44 normalizer: ctx_ref.normalizer.as_ptr(),
45 type_function_runtime: ctx_ref.type_function_runtime.as_ptr(),
46 scope: ctx_ref.scope.as_ptr(),
47 ice: ctx_ref.ice.as_ptr(),
48 limits: unsafe { core::ptr::read(ctx_ref.limits.as_ptr() as *const _) },
49 subtyping,
50 call_loc: location,
51 };
52
53 let mut unique_types: DenseHashSet<TypeId> = DenseHashSet::new(core::ptr::null());
54 let resolution: OverloadResolution = resolver.resolve_overload(
55 fn_ty,
56 args_pack,
57 location,
58 &mut unique_types as *mut DenseHashSet<TypeId>,
59 false,
60 );
61
62 if resolution.ok.is_empty() && resolution.potential_overloads.is_empty() {
63 return None;
64 }
65
66 let selected = resolution.get_unambiguous_overload();
67
68 let selected_overload = selected.overload?;
69
70 let mut ret_pack = unsafe {
71 (*ctx_ref.arena.as_ptr()).fresh_type_pack(ctx_ref.scope.as_ptr(), Polarity::Positive)
72 };
73 let prospective_function = unsafe {
74 (*ctx_ref.arena.as_ptr()).add_type(FunctionType::function_type_new(
75 args_pack, ret_pack, None, false,
76 ))
77 };
78
79 let mut unifier = Unifier2::unifier_2_not_null_type_arena_not_null_builtin_types_not_null_scope_not_null_internal_error_reporter(
81 ctx_ref.arena,
82 ctx_ref.builtins,
83 ctx_ref.scope,
84 ctx_ref.ice,
85 );
86
87 let unify_result = unifier.unify(selected_overload, prospective_function);
88
89 match unify_result {
90 UnifyResult::Ok => {}
91 UnifyResult::OccursCheckFailed => return None,
92 UnifyResult::TooComplex => return None,
93 }
94
95 if !unifier.generic_substitutions.empty() || !unifier.generic_pack_substitutions.empty() {
96 let mut subtyping2 = Subtyping::subtyping_owned(
97 ctx_ref.builtins.as_ptr(),
98 ctx_ref.arena.as_ptr(),
99 ctx_ref.normalizer.as_ptr(),
100 ctx_ref.type_function_runtime.as_ptr(),
101 ctx_ref.ice.as_ptr(),
102 );
103
104 let mut seen: DenseHashSet<TypeId> = DenseHashSet::new(core::ptr::null());
105 let new_ret_tp =
106 get_approximate_return_type_for_function_call(selected_overload, &mut seen)
107 .unwrap_or(unsafe { ctx_ref.builtins.as_ref().errorTypePack });
108
109 let subst = instantiate_2(
112 ctx_ref.arena.as_ptr(),
113 unifier.generic_substitutions.clone(),
114 unifier.generic_pack_substitutions.clone(),
115 &mut subtyping2 as *mut Subtyping,
116 ctx_ref.scope.as_ptr(),
117 new_ret_tp,
118 );
119
120 let subst = subst?;
121 ret_pack = subst;
122 }
123
124 for &ty in &unifier.new_fresh_types {
129 track_interior_free_type(ctx_ref.scope.as_ptr(), ty);
130 }
131 for &tp in &unifier.new_fresh_type_packs {
132 track_interior_free_type_pack(ctx_ref.scope.as_ptr(), tp);
133 }
134
135 Some(ret_pack)
136}