luaur_analysis/methods/
constraint_solver_try_dispatch_constraint_solver_alt_i.rs1use crate::enums::polarity::Polarity;
2use crate::functions::begin_type_pack::begin_type_pack_id;
3use crate::functions::end_type_pack::end_type_pack_id;
4use crate::functions::find_blocked_arg_types_in::find_blocked_arg_types_in;
5use crate::functions::flatten_type_pack::flatten_type_pack_id;
6use crate::functions::follow_type::follow_type_id;
7use crate::functions::follow_type_pack::follow_type_pack_id;
8use crate::functions::get_constraint::get_constraint;
9use crate::functions::get_type_alt_j::get_type_id;
10use crate::functions::push_type_into::push_type_into;
11use crate::functions::unwrap_group::unwrap_group;
12use crate::records::builtin_types::BuiltinTypes;
13use crate::records::constraint::Constraint;
14use crate::records::constraint_solver::ConstraintSolver;
15use crate::records::constraint_v::ConstraintV;
16use crate::records::dense_hash_map::DenseHashMap;
17use crate::records::dense_hash_set::DenseHashSet;
18use crate::records::function_check_constraint::FunctionCheckConstraint;
19use crate::records::function_type::FunctionType;
20use crate::records::generic_type::GenericType;
21use crate::records::incomplete_inference::IncompleteInference;
22use crate::records::internal_error_reporter::InternalErrorReporter;
23use crate::records::normalizer::Normalizer;
24use crate::records::push_type_constraint::PushTypeConstraint;
25use crate::records::push_type_result::PushTypeResult;
26use crate::records::scope::Scope;
27use crate::records::subtyping::Subtyping;
28use crate::records::type_arena::TypeArena;
29use crate::records::type_check_limits::TypeCheckLimits;
30use crate::records::type_function_runtime::TypeFunctionRuntime;
31use crate::records::type_pair_hash::TypePairHash;
32use crate::records::unifier_2::Unifier2;
33use crate::type_aliases::constraint_v::ConstraintV as ConstraintVMember;
34use crate::type_aliases::type_id::TypeId;
35use crate::type_aliases::type_pack_id::TypePackId;
36use alloc::vec::Vec;
37use core::ffi::c_void;
38use core::ptr::NonNull;
39use luaur_ast::records::ast_expr::AstExpr;
40use luaur_ast::records::ast_expr_call::AstExprCall;
41use luaur_ast::records::location::Location;
42use luaur_ast::records::position::Position;
43use luaur_common::records::dense_hash_map::DenseHashMap as CommonDenseHashMap;
44use luaur_common::records::dense_hash_set::DenseHashSet as CommonDenseHashSet;
45
46impl ConstraintSolver {
47 pub fn try_dispatch_function_check_constraint_not_null_constraint_bool(
48 &mut self,
49 c: &FunctionCheckConstraint,
50 constraint: *const Constraint,
51 force: bool,
52 ) -> bool {
53 let fn_ty = unsafe { follow_type_id(c.fn_type) };
54 let args_pack = unsafe { follow_type_pack_id(c.args_pack) };
55
56 if self.is_blocked_type_id(fn_ty) {
57 return self.block_type_id_not_null_constraint(fn_ty, constraint);
58 }
59
60 if self.is_blocked_type_pack_id(args_pack) {
61 return true;
62 }
63
64 let blocked_types = find_blocked_arg_types_in(
65 c.call_site,
66 c.ast_types as *mut CommonDenseHashMap<*const AstExpr, TypeId>,
67 );
68 for ty in &blocked_types {
69 self.block_type_id_not_null_constraint(*ty, constraint);
70 }
71 if !blocked_types.is_empty() {
72 return false;
73 }
74
75 let ftv = unsafe { get_type_id::<FunctionType>(fn_ty) };
76 if ftv.is_null() {
77 return true;
78 }
79
80 let mut replacements: DenseHashMap<TypeId, TypeId> =
81 DenseHashMap::new(core::ptr::null_mut());
82 let mut replacement_packs: DenseHashMap<TypePackId, TypePackId> =
83 DenseHashMap::new(core::ptr::null_mut());
84
85 let mut generic_types_and_packs: DenseHashSet<*const c_void> =
86 DenseHashSet::new(core::ptr::null_mut());
87
88 let mut u2 = Unifier2::unifier_2_not_null_type_arena_not_null_builtin_types_not_null_scope_not_null_internal_error_reporter(
89 NonNull::new(self.arena).unwrap(),
90 NonNull::new(self.builtin_types).unwrap(),
91 NonNull::new(constraint_scope(constraint)).unwrap(),
92 NonNull::new(&self.ice_reporter as *const InternalErrorReporter as *mut InternalErrorReporter).unwrap(),
93 );
94
95 for generic in unsafe { &(*ftv).generics } {
96 let gty = unsafe { get_type_id::<GenericType>(follow_type_id(*generic)) };
99 if !gty.is_null() {
100 let repl_ty = if unsafe { (*gty).polarity } == Polarity::Negative {
101 unsafe { (*self.builtin_types).neverType }
102 } else {
103 unsafe { (*self.builtin_types).unknownType }
104 };
105 replacements.try_insert(*generic, repl_ty);
106 generic_types_and_packs.insert_mut(*generic as *const c_void);
107 }
108 }
109
110 for generic_pack in unsafe { &(*ftv).generic_packs } {
111 replacement_packs.try_insert(*generic_pack, unsafe {
112 (*self.builtin_types).unknownTypePack
113 });
114 generic_types_and_packs.insert_mut(*generic_pack as *const c_void);
115 }
116
117 let (expected_args, _) = flatten_type_pack_id(unsafe { (*ftv).arg_types });
118 let (arg_pack_head, _) = flatten_type_pack_id(args_pack);
119
120 let type_offset = if unsafe { (*c.call_site).self_ } {
123 1
124 } else {
125 0
126 };
127
128 let mut subtyping = Subtyping::subtyping_owned(
129 self.builtin_types,
130 self.arena,
131 self.normalizer,
132 self.type_function_runtime,
133 &self.ice_reporter as *const InternalErrorReporter as *mut InternalErrorReporter,
134 );
135
136 let call_site_args_size = unsafe { (*c.call_site).args.size };
137 let args_data = unsafe { (*c.call_site).args.data };
138
139 for i in 0..call_site_args_size {
140 if i as usize + type_offset >= expected_args.len()
141 || i as usize + type_offset >= arg_pack_head.len()
142 {
143 break;
144 }
145
146 let expected_arg_ty =
147 unsafe { follow_type_id(expected_args[i as usize + type_offset]) };
148 let expr = unsafe { unwrap_group(*args_data.add(i as usize)) };
149
150 let result = push_type_into(
151 NonNull::new(c.ast_types as *mut CommonDenseHashMap<*const AstExpr, TypeId>)
152 .unwrap(),
153 NonNull::new(
154 c.ast_expected_types as *mut CommonDenseHashMap<*const AstExpr, TypeId>,
155 )
156 .unwrap(),
157 NonNull::new(self as *mut ConstraintSolver).unwrap(),
158 NonNull::new(constraint as *mut Constraint).unwrap(),
159 NonNull::new(&mut generic_types_and_packs as *mut DenseHashSet<*const c_void>)
160 .unwrap(),
161 NonNull::new(&mut u2 as *mut Unifier2).unwrap(),
162 NonNull::new(&mut subtyping as *mut Subtyping).unwrap(),
163 expected_arg_ty,
164 expr as *const AstExpr,
165 );
166
167 if !force && !result.incomplete_types.is_empty() {
168 for incomplete in &result.incomplete_types {
169 let addition = self.push_constraint(
170 NonNull::new(constraint_scope(constraint)).unwrap(),
171 unsafe { (*constraint).location },
172 ConstraintV::PushType(PushTypeConstraint {
173 expectedType: incomplete.expectedType,
174 targetType: incomplete.targetType,
175 astTypes: c.ast_types,
176 astExpectedTypes: c.ast_expected_types,
177 expr: incomplete.expr as *const AstExpr,
178 }),
179 );
180 self.inherit_blocks(constraint, addition.as_ptr());
181 }
182 }
183 }
184
185 let incomplete_subtypes = u2.incomplete_subtypes.clone();
186 for c_item in incomplete_subtypes {
187 let addition = self.push_constraint(
188 NonNull::new(constraint_scope(constraint)).unwrap(),
189 unsafe { (*constraint).location },
190 c_item,
191 );
192 self.inherit_blocks(constraint, addition.as_ptr());
193 }
194
195 true
196 }
197}
198
199fn constraint_scope(c: *const Constraint) -> *mut Scope {
200 unsafe { (*c).scope }
201}