1use crate::enums::polarity::Polarity;
2use crate::enums::unify_result::UnifyResult;
3use crate::functions::find_unique_types_ast_utils_alt_d::find_unique_types;
4use crate::functions::flatten_type_pack::flatten_type_pack_id;
5use crate::functions::follow_type::follow_type_id;
6use crate::functions::follow_type_pack::follow_type_pack_id;
7use crate::functions::get_approximate_return_type_for_function_call_type_utils_alt_b::get_approximate_return_type_for_function_call_type_id;
8use crate::functions::get_mutable_type::get_mutable_type_id;
9use crate::functions::get_type_alt_j::get_type_id;
10use crate::functions::instantiate_2_instantiation_2::instantiate_2 as instantiate_2_type_id;
11use crate::functions::instantiate_2_instantiation_2_alt_b::instantiate_2;
12use crate::functions::shallow_clone_clone_alt_b::shallow_clone;
13use crate::functions::track_interior_free_type::track_interior_free_type;
14use crate::functions::track_interior_free_type_pack::track_interior_free_type_pack;
15use crate::records::any_type::AnyType;
16use crate::records::builtin_types::BuiltinTypes;
17use crate::records::clone_state::CloneState;
18use crate::records::constraint::Constraint;
19use crate::records::constraint_solver::ConstraintSolver;
20use crate::records::free_type::FreeType;
21use crate::records::function_call_constraint::FunctionCallConstraint;
22use crate::records::function_type::FunctionType;
23use crate::records::generic_type_visitor::GenericTypeVisitorTrait;
24use crate::records::instantiation_queuer::InstantiationQueuer;
25use crate::records::instantiation_queuer_deprecated::InstantiationQueuerDeprecated;
26use crate::records::internal_error_reporter::InternalErrorReporter;
27use crate::records::intersection_type::IntersectionType;
28use crate::records::iterative_type_visitor::IterativeTypeVisitorTrait;
29use crate::records::magic_function_call_context::MagicFunctionCallContext;
30use crate::records::magic_refinement_context::MagicRefinementContext;
31use crate::records::never_type::NeverType;
32use crate::records::occurs_check_failed::OccursCheckFailed;
33use crate::records::overload_resolver::OverloadResolver;
34use crate::records::subtyping::Subtyping;
35use crate::records::unification_too_complex::UnificationTooComplex;
36use crate::records::unifier_2::Unifier2;
37use crate::records::union_type::UnionType;
38use crate::records::unknown_type::UnknownType;
39use crate::type_aliases::error_type::ErrorType;
40use crate::type_aliases::type_id::TypeId;
41use core::ptr::NonNull;
42use luaur_ast::records::ast_node::AstNode;
43use luaur_common::records::dense_hash_map::DenseHashMap;
44use luaur_common::records::dense_hash_set::DenseHashSet;
45use luaur_common::FFlag;
46
47impl ConstraintSolver {
48 pub fn try_dispatch_function_call_constraint_not_null_constraint_bool(
49 &mut self,
50 c: &FunctionCallConstraint,
51 constraint: *const Constraint,
52 _force: bool,
53 ) -> bool {
54 let mut fn_ty = unsafe { follow_type_id(c.fn_type) };
55 let args_pack = unsafe { follow_type_pack_id(c.args_pack) };
56 let result = unsafe { follow_type_pack_id(c.result) };
57
58 if self.is_blocked_type_id(fn_ty) {
59 return self.block_type_id_not_null_constraint(c.fn_type, constraint);
60 }
61
62 if unsafe { !get_type_id::<AnyType>(fn_ty).is_null() } {
63 self.bind_not_null_constraint_type_pack_id_type_pack_id(constraint, c.result, unsafe {
64 (*self.builtin_types).anyTypePack
65 });
66 self.fill_in_discriminant_types(constraint, &c.discriminant_types);
67 return true;
68 }
69
70 if unsafe { !get_type_id::<ErrorType>(fn_ty).is_null() } {
71 self.bind_not_null_constraint_type_pack_id_type_pack_id(constraint, c.result, unsafe {
72 (*self.builtin_types).errorTypePack
73 });
74 self.fill_in_discriminant_types(constraint, &c.discriminant_types);
75 return true;
76 }
77
78 if unsafe { !get_type_id::<NeverType>(fn_ty).is_null() } {
79 self.bind_not_null_constraint_type_pack_id_type_pack_id(constraint, c.result, unsafe {
80 (*self.builtin_types).neverTypePack
81 });
82 self.fill_in_discriminant_types(constraint, &c.discriminant_types);
83 return true;
84 }
85
86 let (args_head, args_tail) = flatten_type_pack_id(args_pack);
87 let mut blocked = false;
88
89 for arg in args_head {
90 if self.is_blocked_type_id(arg) {
91 self.block_type_id_not_null_constraint(arg, constraint);
92 blocked = true;
93 }
94 }
95
96 if let Some(tail) = args_tail {
97 if self.is_blocked_type_pack_id(tail) {
98 self.block_type_pack_id_not_null_constraint(tail, constraint);
99 blocked = true;
100 }
101 }
102
103 if blocked {
104 return false;
105 }
106
107 let scope = unsafe { (*constraint).scope };
108 let location = unsafe { (*constraint).location };
109
110 let mut args_pack = args_pack;
111
112 fn collapse(parts: &[TypeId]) -> Option<TypeId> {
113 let first = parts.first().copied()?;
114 let first = unsafe { follow_type_id(first) };
115
116 for part in parts {
117 if unsafe { follow_type_id(*part) } != first {
118 return None;
119 }
120 }
121
122 Some(first)
123 }
124
125 if let Some(utv) = unsafe { get_type_id::<UnionType>(fn_ty).as_ref() } {
126 fn_ty = collapse(&utv.options).unwrap_or(fn_ty);
127 } else if let Some(itv) = unsafe { get_type_id::<IntersectionType>(fn_ty).as_ref() } {
128 fn_ty = collapse(&itv.parts).unwrap_or(fn_ty);
129 }
130
131 let mut used_magic = false;
132 if let Some(ftv) = unsafe { get_type_id::<FunctionType>(fn_ty).as_ref() } {
133 if let Some(magic) = &ftv.magic {
134 if !c.call_site.is_null() {
135 used_magic = (magic.infer)(&MagicFunctionCallContext {
136 solver: NonNull::new(self as *mut ConstraintSolver).unwrap(),
137 constraint: NonNull::new(constraint as *mut Constraint).unwrap(),
138 call_site: NonNull::new(c.call_site).unwrap(),
139 arguments: c.args_pack,
140 result,
141 });
142 (magic.refine)(&MagicRefinementContext {
143 scope,
144 call_site: c.call_site,
145 discriminant_types: c.discriminant_types.clone(),
146 });
147 }
148 }
149 }
150
151 if luaur_common::FFlag::LuauExplicitTypeInstantiationSupport.get()
152 && (!c.type_arguments.is_empty() || !c.type_pack_arguments.is_empty())
153 {
154 fn_ty = self.instantiate_function_type(
155 c.fn_type,
156 &c.type_arguments,
157 &c.type_pack_arguments,
158 scope,
159 &location,
160 );
161 }
162
163 self.fill_in_discriminant_types(constraint, &c.discriminant_types);
164
165 let mut overload_to_use = fn_ty;
166
167 if unsafe { get_type_id::<FunctionType>(overload_to_use).is_null() } {
168 let mut resolver = OverloadResolver::new(
169 self.builtin_types,
170 self.arena,
171 self.normalizer,
172 self.type_function_runtime,
173 scope,
174 &mut self.ice_reporter as *mut InternalErrorReporter,
175 &mut self.limits as *mut _,
176 location,
177 );
178
179 let mut unique_types: DenseHashSet<TypeId> = DenseHashSet::new(core::ptr::null_mut());
180 if !c.call_site.is_null() {
181 if let Some(module) = &self.module {
182 let module_ptr = alloc::sync::Arc::as_ptr(module);
183 unsafe {
184 find_unique_types(
185 &mut unique_types as *mut DenseHashSet<TypeId>,
186 (*c.call_site).args.as_slice(),
187 &(*module_ptr).ast_types as *const _,
188 );
189 }
190 }
191 }
192
193 let resolution = resolver.resolve_overload(
194 overload_to_use,
195 args_pack,
196 if c.call_site.is_null() {
197 luaur_ast::records::location::Location::default()
198 } else {
199 unsafe { (*(*c.call_site).func).base.location }
200 },
201 &mut unique_types as *mut DenseHashSet<TypeId>,
202 true,
203 );
204
205 let selected = resolution.get_unambiguous_overload();
206 if let Some(overload) = selected.overload {
207 overload_to_use = overload;
208 } else {
209 self.bind_not_null_constraint_type_pack_id_type_pack_id(
210 constraint,
211 c.result,
212 unsafe { (*self.builtin_types).errorTypePack },
213 );
214 return true;
215 }
216
217 if resolution.metamethods.contains(&overload_to_use) {
218 args_pack = unsafe {
219 (*self.arena).add_type_pack_vector_type_id_optional_type_pack_id(
220 alloc::vec![fn_ty],
221 Some(args_pack),
222 )
223 };
224 }
225 }
226
227 let ret_tp = unsafe { (*self.arena).fresh_type_pack(scope, Polarity::Positive) };
228 track_interior_free_type_pack(scope, ret_tp);
229
230 let inferred_ty = unsafe {
231 (*self.arena).add_type(FunctionType::function_type_new(
232 args_pack, ret_tp, None, false,
233 ))
234 };
235
236 let mut u2 = Unifier2::unifier_2_not_null_type_arena_not_null_builtin_types_not_null_scope_not_null_internal_error_reporter(
237 NonNull::new(self.arena).unwrap(),
238 NonNull::new(self.builtin_types).unwrap(),
239 NonNull::new(scope).unwrap(),
240 NonNull::new(&self.ice_reporter as *const InternalErrorReporter as *mut InternalErrorReporter).unwrap(),
241 );
242
243 let unify_result = u2.unify(overload_to_use, inferred_ty);
244
245 for free_ty in u2.new_fresh_types.iter().copied() {
246 track_interior_free_type(scope, free_ty);
247 }
248 for free_tp in u2.new_fresh_type_packs.iter().copied() {
249 track_interior_free_type_pack(scope, free_tp);
250 }
251
252 let mut result_tp = ret_tp;
253 if !u2.generic_substitutions.empty() || !u2.generic_pack_substitutions.empty() {
254 let mut subtyping = Subtyping::subtyping_owned(
255 self.builtin_types,
256 self.arena,
257 self.normalizer,
258 self.type_function_runtime,
259 &self.ice_reporter as *const InternalErrorReporter as *mut InternalErrorReporter,
260 );
261
262 let mut has_bound = false;
263 for (_, ty) in u2.generic_substitutions.iter() {
264 if let Some(ftv) = unsafe { get_type_id::<FreeType>(*ty).as_ref() } {
265 let lower_bound = unsafe { follow_type_id(ftv.lower_bound) };
266 let upper_bound = unsafe { follow_type_id(ftv.upper_bound) };
267 has_bound = unsafe { get_type_id::<NeverType>(lower_bound).is_null() }
268 || unsafe { get_type_id::<UnknownType>(upper_bound).is_null() };
269
270 if has_bound {
271 break;
272 }
273 }
274 }
275
276 if unsafe { !get_type_id::<FunctionType>(overload_to_use).is_null() } && has_bound {
277 let mut clone_state = CloneState {
278 builtin_types: self.builtin_types,
279 seen_types: DenseHashMap::new(core::ptr::null()),
280 seen_type_packs: DenseHashMap::new(core::ptr::null()),
281 };
282
283 let cloned_ty = shallow_clone(
284 overload_to_use,
285 unsafe { &mut *self.arena },
286 &mut clone_state,
287 true,
288 );
289 let cloned_fn = unsafe { get_mutable_type_id::<FunctionType>(cloned_ty) };
290 unsafe {
291 (*cloned_fn).generics.clear();
292 (*cloned_fn).generic_packs.clear();
293 }
294
295 if let Some(subst) = instantiate_2_type_id(
296 self.arena,
297 u2.generic_substitutions.clone(),
298 u2.generic_pack_substitutions.clone(),
299 &mut subtyping as *mut Subtyping,
300 scope,
301 cloned_ty,
302 ) {
303 overload_to_use = unsafe { follow_type_id(subst) };
304
305 if let Some(instantiated_fn) =
306 unsafe { get_type_id::<FunctionType>(overload_to_use).as_ref() }
307 {
308 result_tp = unsafe { follow_type_pack_id(instantiated_fn.ret_types) };
309 } else {
310 self.report_error_type_error_data_location(
311 crate::records::code_too_complex::CodeTooComplex::default().into(),
312 &location,
313 );
314 result_tp = unsafe { (*self.builtin_types).errorTypePack };
315 }
316 } else {
317 self.report_error_type_error_data_location(
318 crate::records::code_too_complex::CodeTooComplex::default().into(),
319 &location,
320 );
321 result_tp = unsafe { (*self.builtin_types).errorTypePack };
322 }
323 } else {
324 let approximate_ret =
325 get_approximate_return_type_for_function_call_type_id(overload_to_use)
326 .unwrap_or(unsafe { (*self.builtin_types).errorTypePack });
327
328 if let Some(subst) = instantiate_2(
329 self.arena,
330 u2.generic_substitutions.clone(),
331 u2.generic_pack_substitutions.clone(),
332 &mut subtyping as *mut Subtyping,
333 scope,
334 approximate_ret,
335 ) {
336 result_tp = subst;
337 } else {
338 self.report_error_type_error_data_location(
339 crate::records::code_too_complex::CodeTooComplex::default().into(),
340 &location,
341 );
342 result_tp = unsafe { (*self.builtin_types).errorTypePack };
343 }
344 }
345 }
346
347 if !used_magic {
348 self.bind_not_null_constraint_type_pack_id_type_pack_id(
349 constraint, c.result, result_tp,
350 );
351 }
352
353 for (expanded, additions) in u2.expanded_free_types.iter() {
354 for addition in additions {
355 self.upper_bound_contributors
356 .get_or_insert(*expanded)
357 .push((location, *addition));
358 }
359 }
360
361 match unify_result {
362 UnifyResult::Ok => {
363 if !c.call_site.is_null() && !c.ast_overload_resolved_types.is_null() {
364 unsafe {
365 *(*c.ast_overload_resolved_types)
366 .get_or_insert(c.call_site as *const AstNode) = if used_magic {
367 inferred_ty
368 } else {
369 overload_to_use
370 };
371 }
372 }
373 }
374 UnifyResult::TooComplex => self.report_error_type_error_data_location(
375 UnificationTooComplex::default().into(),
376 &location,
377 ),
378 UnifyResult::OccursCheckFailed => self.report_error_type_error_data_location(
379 OccursCheckFailed::default().into(),
380 &location,
381 ),
382 }
383
384 if FFlag::LuauIterativeInstantiationQueuer.get() {
385 let mut queuer = InstantiationQueuer::instantiation_queuer(
386 NonNull::new(scope).unwrap(),
387 &location,
388 self as *mut ConstraintSolver,
389 );
390 queuer.run_type_id(overload_to_use);
391 if FFlag::LuauAlsoInstantiateInferredArguments.get() {
392 queuer.run_type_pack_id(args_pack);
393 }
394 queuer.run_type_pack_id(result);
395 } else {
396 let mut queuer = InstantiationQueuerDeprecated::instantiation_queuer_deprecated_instantiation_queuer_deprecated(
397 NonNull::new(scope).unwrap(),
398 &location,
399 self as *mut ConstraintSolver,
400 );
401 queuer.traverse_type_id(overload_to_use);
402 if FFlag::LuauAlsoInstantiateInferredArguments.get() {
403 queuer.traverse_type_pack_id(args_pack);
404 }
405 queuer.traverse_type_pack_id(result);
406 }
407
408 if !FFlag::LuauConstraintGraph.get() {
409 self.unblock_type_pack_id_location(c.result, location);
410 }
411
412 true
413 }
414}