Skip to main content

luaur_analysis/methods/
constraint_solver_try_dispatch_constraint_solver_alt_t.rs

1use crate::functions::begin_type_pack::begin_type_pack_id;
2use crate::functions::end_type_pack::end_type_pack_id;
3use crate::functions::follow_type::follow_type_id;
4use crate::functions::get_type_alt_j::get_type_id;
5use crate::records::constraint::Constraint;
6use crate::records::constraint_solver::ConstraintSolver;
7use crate::records::contains_any_generic_deprecated::ContainsAnyGenericDeprecated;
8use crate::records::free_type::FreeType;
9use crate::records::free_type_pack::FreeTypePack;
10use crate::records::function_type::FunctionType;
11use crate::records::push_function_type_constraint::PushFunctionTypeConstraint;
12use luaur_common::FFlag;
13
14impl ConstraintSolver {
15    pub fn try_dispatch_push_function_type_constraint_not_null_constraint(
16        &mut self,
17        c: &PushFunctionTypeConstraint,
18        constraint: *const Constraint,
19    ) -> bool {
20        let expected_fn = unsafe {
21            let followed = follow_type_id(c.expected_function_type);
22            get_type_id::<FunctionType>(followed)
23        };
24
25        let fn_ty = unsafe {
26            let followed = follow_type_id(c.function_type);
27            get_type_id::<FunctionType>(followed)
28        };
29
30        if expected_fn.is_null() || fn_ty.is_null() {
31            return true;
32        }
33
34        let expected_fn_ref = unsafe { &*expected_fn };
35        let fn_ty_ref = unsafe { &*fn_ty };
36
37        if FFlag::LuauInstantiateFunctionTypeBeforePush.get() {
38            // instantiate is not yet translated; stubbing the logic as per the source comment
39            // "NOTE: This logic could probably be combined with that of FunctionCheckConstraint"
40            // Since instantiate is not available, we skip this block and rely on the fallback behavior
41        }
42
43        let mut expected_params = unsafe { begin_type_pack_id(expected_fn_ref.arg_types) };
44        let mut params = unsafe { begin_type_pack_id(fn_ty_ref.arg_types) };
45
46        let expected_params_end = unsafe { end_type_pack_id(expected_fn_ref.arg_types) };
47        let params_end = unsafe { end_type_pack_id(fn_ty_ref.arg_types) };
48
49        if expected_params.operator_eq(&expected_params_end) || params.operator_eq(&params_end) {
50            return true;
51        }
52
53        if c.is_self {
54            let params_current = unsafe { *params.operator_deref() };
55            if !unsafe { get_type_id::<FreeType>(follow_type_id(params_current)) }.is_null() {
56                if !FFlag::LuauConstraintGraph.get() {
57                    self.deprecate_d_shift_references(params_current, unsafe {
58                        *expected_params.operator_deref()
59                    });
60                }
61                self.bind_not_null_constraint_type_id_type_id(constraint, params_current, unsafe {
62                    *expected_params.operator_deref()
63                });
64            }
65            expected_params.operator_inc();
66            params.operator_inc();
67        }
68
69        let mut idx: usize = 0;
70        while idx < unsafe { (*c.expr).args.size }
71            && !expected_params.operator_eq(&expected_params_end)
72            && !params.operator_eq(&params_end)
73        {
74            let arg = unsafe { *(*c.expr).args.data.add(idx) };
75            let annotation = unsafe { (*arg).annotation };
76            let params_current = unsafe { *params.operator_deref() };
77            let free_type_ptr = unsafe { get_type_id::<FreeType>(follow_type_id(params_current)) };
78
79            if annotation.is_null()
80                && !free_type_ptr.is_null()
81                && (FFlag::LuauInstantiateFunctionTypeBeforePush.get()
82                    || !ContainsAnyGenericDeprecated::has_any_generic(unsafe {
83                        *expected_params.operator_deref()
84                    }))
85            {
86                if !FFlag::LuauConstraintGraph.get() {
87                    self.deprecate_d_shift_references(params_current, unsafe {
88                        *expected_params.operator_deref()
89                    });
90                }
91                self.bind_not_null_constraint_type_id_type_id(constraint, params_current, unsafe {
92                    *expected_params.operator_deref()
93                });
94            }
95
96            expected_params.operator_inc();
97            params.operator_inc();
98            idx += 1;
99        }
100
101        if unsafe { (*c.expr).return_annotation.is_null() }
102            && !unsafe {
103                crate::functions::get_type_pack::get_type_pack_id::<FreeTypePack>(
104                    fn_ty_ref.ret_types,
105                )
106            }
107            .is_null()
108            && (FFlag::LuauInstantiateFunctionTypeBeforePush.get()
109                || !ContainsAnyGenericDeprecated::has_any_generic_type_pack_id(
110                    expected_fn_ref.ret_types,
111                ))
112        {
113            self.bind_not_null_constraint_type_pack_id_type_pack_id(
114                constraint,
115                fn_ty_ref.ret_types,
116                expected_fn_ref.ret_types,
117            );
118        }
119
120        true
121    }
122}