Skip to main content

luaur_analysis/methods/
constraint_solver_try_dispatch_constraint_solver_alt_q.rs

1//! `bool ConstraintSolver::tryDispatch(const ReducePackConstraint& c, NotNull<const Constraint> constraint, bool force)`
2//! (`Analysis/src/ConstraintSolver.cpp:2935-2972`, hand-ported faithfully).
3
4use core::ffi::c_void;
5use core::ptr::NonNull;
6
7use crate::functions::follow_type_pack::follow_type_pack_id;
8use crate::functions::get_error::get_type_error;
9use crate::functions::reduce_type_functions_type_function_alt_b::reduce_type_functions;
10use crate::records::constraint::Constraint;
11use crate::records::constraint_solver::ConstraintSolver;
12use crate::records::reduce_pack_constraint::ReducePackConstraint;
13use crate::records::type_function_context::TypeFunctionContext;
14use crate::records::uninhabited_type_function::UninhabitedTypeFunction;
15use crate::records::uninhabited_type_pack_function::UninhabitedTypePackFunction;
16
17impl ConstraintSolver {
18    pub fn try_dispatch_reduce_pack_constraint_not_null_constraint_bool(
19        &mut self,
20        c: &ReducePackConstraint,
21        constraint: *const Constraint,
22        force: bool,
23    ) -> bool {
24        let tp = unsafe { follow_type_pack_id(c.tp) };
25
26        let scope = unsafe { (*constraint).scope };
27        let location = unsafe { (*constraint).location };
28
29        let mut context = TypeFunctionContext::from_solver(
30            NonNull::new(self as *mut ConstraintSolver).unwrap(),
31            NonNull::new(scope).unwrap(),
32            NonNull::new(constraint as *mut Constraint).unwrap(),
33            NonNull::new(self.subtyping).unwrap(),
34        );
35        let result = reduce_type_functions(
36            tp,
37            location,
38            NonNull::new(&mut context as *mut TypeFunctionContext).unwrap(),
39            force,
40        );
41
42        for r in result.reduced_types.iter() {
43            self.unblock_type_id_location(*r, location);
44        }
45
46        for r in result.reduced_packs.iter() {
47            self.unblock_type_pack_id_location(*r, location);
48        }
49
50        let reduction_finished = result.blocked_types.empty() && result.blocked_packs.empty();
51
52        if force || reduction_finished {
53            // if we're completely dispatching this constraint, we want to record any uninhabited type functions to unblock.
54            for error in result.errors.iter() {
55                let utf = get_type_error::<UninhabitedTypeFunction>(error);
56                if !utf.is_null() {
57                    self.uninhabited_type_functions
58                        .insert(unsafe { (*utf).ty } as *const c_void);
59                } else {
60                    let utpf = get_type_error::<UninhabitedTypePackFunction>(error);
61                    if !utpf.is_null() {
62                        self.uninhabited_type_functions
63                            .insert(unsafe { (*utpf).tp } as *const c_void);
64                    }
65                }
66            }
67        }
68
69        if force {
70            return true;
71        }
72
73        for b in result.blocked_types.iter() {
74            self.block_type_id_not_null_constraint(*b, constraint);
75        }
76
77        for b in result.blocked_packs.iter() {
78            self.block_type_pack_id_not_null_constraint(*b, constraint);
79        }
80
81        reduction_finished
82    }
83}