Skip to main content

luaur_analysis/methods/
constraint_solver_try_dispatch_constraint_solver_alt_i.rs

1use 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            // We may see non-generic types here, for example when evaluating a
97            // recursive function call.
98            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        // If this is a self call, the types will have more elements than the AST call.
121        // We don't attempt to perform bidirectional inference on the self type.
122        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}