Skip to main content

luaur_analysis/methods/
constraint_solver_try_dispatch_constraint_solver_alt_p.rs

1//! `bool ConstraintSolver::tryDispatch(const ReduceConstraint& c, NotNull<const Constraint> constraint, bool force)`
2//! (`Analysis/src/ConstraintSolver.cpp:2879-2933`, hand-ported faithfully).
3
4use core::ffi::c_void;
5use core::ptr::NonNull;
6
7use crate::functions::follow_type::follow_type_id;
8use crate::functions::get_error::get_type_error;
9use crate::functions::get_type_alt_j::get_type_id;
10use crate::functions::reduce_type_functions_type_function::reduce_type_functions;
11use crate::records::constraint::Constraint;
12use crate::records::constraint_solver::ConstraintSolver;
13use crate::records::reduce_constraint::ReduceConstraint;
14use crate::records::type_function_context::TypeFunctionContext;
15use crate::records::type_function_instance_type::TypeFunctionInstanceType;
16use crate::records::uninhabited_type_function::UninhabitedTypeFunction;
17use crate::records::uninhabited_type_pack_function::UninhabitedTypePackFunction;
18
19impl ConstraintSolver {
20    pub fn try_dispatch_reduce_constraint_not_null_constraint_bool(
21        &mut self,
22        c: &ReduceConstraint,
23        constraint: *const Constraint,
24        force: bool,
25    ) -> bool {
26        let mut ty = unsafe { follow_type_id(c.ty) };
27
28        let scope = unsafe { (*constraint).scope };
29        let location = unsafe { (*constraint).location };
30
31        let mut context = TypeFunctionContext::from_solver(
32            NonNull::new(self as *mut ConstraintSolver).unwrap(),
33            NonNull::new(scope).unwrap(),
34            NonNull::new(constraint as *mut Constraint).unwrap(),
35            NonNull::new(self.subtyping).unwrap(),
36        );
37        let mut result = reduce_type_functions(
38            ty,
39            location,
40            NonNull::new(&mut context as *mut TypeFunctionContext).unwrap(),
41            force,
42        );
43
44        for r in result.reduced_types.iter() {
45            self.unblock_type_id_location(*r, location);
46        }
47
48        for r in result.reduced_packs.iter() {
49            self.unblock_type_pack_id_location(*r, location);
50        }
51
52        for ity in result.irreducible_types.iter() {
53            self.uninhabited_type_functions
54                .insert(*ity as *const c_void);
55            self.unblock_type_id_location(*ity, location);
56        }
57
58        let reduction_finished = result.blocked_types.empty() && result.blocked_packs.empty();
59
60        ty = unsafe { follow_type_id(ty) };
61
62        // If we couldn't reduce this type function, stick it in the set!
63        if unsafe { !get_type_id::<TypeFunctionInstanceType>(ty).is_null() }
64            && result.irreducible_types.find(&ty).is_none()
65        {
66            *self.type_functions_to_finalize.get_or_insert(ty) = constraint;
67        }
68
69        if force || reduction_finished {
70            for message in core::mem::take(&mut result.messages) {
71                self.report_error_type_error(message);
72            }
73
74            // if we're completely dispatching this constraint, we want to record any uninhabited type functions to unblock.
75            for error in result.errors.iter() {
76                let utf = get_type_error::<UninhabitedTypeFunction>(error);
77                if !utf.is_null() {
78                    self.uninhabited_type_functions
79                        .insert(unsafe { (*utf).ty } as *const c_void);
80                } else {
81                    let utpf = get_type_error::<UninhabitedTypePackFunction>(error);
82                    if !utpf.is_null() {
83                        self.uninhabited_type_functions
84                            .insert(unsafe { (*utpf).tp } as *const c_void);
85                    }
86                }
87            }
88        }
89
90        if force {
91            return true;
92        }
93
94        for b in result.blocked_types.iter() {
95            self.block_type_id_not_null_constraint(*b, constraint);
96        }
97
98        for b in result.blocked_packs.iter() {
99            self.block_type_pack_id_not_null_constraint(*b, constraint);
100        }
101
102        reduction_finished
103    }
104}