Skip to main content

luaur_analysis/methods/
constraint_solver_try_dispatch_constraint_solver_alt_e.rs

1use crate::enums::polarity::Polarity;
2use crate::enums::table_state::TableState;
3use crate::functions::extend_type_pack::extend_type_pack;
4use crate::functions::follow_type::follow_type_id;
5use crate::functions::fresh_type::fresh_type;
6use crate::functions::get_type_alt_j::get_type_id;
7use crate::functions::track_interior_free_type::track_interior_free_type;
8use crate::records::constraint::Constraint;
9use crate::records::constraint_solver::ConstraintSolver;
10use crate::records::free_type::FreeType;
11use crate::records::function_type::FunctionType;
12use crate::records::iterable_constraint::IterableConstraint;
13use crate::records::table_indexer::TableIndexer;
14use crate::records::table_type::TableType;
15use crate::records::type_level::TypeLevel;
16use crate::type_aliases::props_type::Props;
17
18impl ConstraintSolver {
19    pub fn try_dispatch_iterable_constraint_not_null_constraint_bool(
20        &mut self,
21        c: &IterableConstraint,
22        constraint: *const Constraint,
23        force: bool,
24    ) -> bool {
25        let iterator = unsafe {
26            extend_type_pack(
27                &mut *self.arena,
28                self.builtin_types,
29                c.iterator,
30                3,
31                alloc::vec::Vec::new(),
32            )
33        };
34
35        if iterator.head.len() < 3 {
36            if let Some(tail) = iterator.tail {
37                if self.is_blocked_type_pack_id(tail) {
38                    return if force {
39                        true
40                    } else {
41                        self.block_type_pack_id_not_null_constraint(tail, constraint)
42                    };
43                }
44            }
45        }
46
47        let mut blocked = false;
48        for ty in &iterator.head {
49            if self.is_blocked_type_id(*ty) {
50                self.block_type_id_not_null_constraint(*ty, constraint);
51                blocked = true;
52            }
53        }
54
55        if blocked {
56            return false;
57        }
58
59        if iterator.head.is_empty() {
60            for ty in &c.variables {
61                self.bind_not_null_constraint_type_id_type_id(constraint, *ty, unsafe {
62                    (*self.builtin_types).errorType
63                });
64            }
65            return true;
66        }
67
68        let next_ty = unsafe { follow_type_id(iterator.head[0]) };
69        if unsafe { !get_type_id::<FreeType>(next_ty).is_null() } {
70            let scope = unsafe { (*constraint).scope };
71            let key_ty = unsafe {
72                fresh_type(
73                    &mut *self.arena,
74                    &*self.builtin_types,
75                    scope,
76                    Polarity::Mixed,
77                )
78            };
79            let value_ty = unsafe {
80                fresh_type(
81                    &mut *self.arena,
82                    &*self.builtin_types,
83                    scope,
84                    Polarity::Mixed,
85                )
86            };
87            track_interior_free_type(scope, key_ty);
88            track_interior_free_type(scope, value_ty);
89
90            let props = Props::default();
91            let table_ty = unsafe {
92                (*self.arena).add_type(
93                    TableType::table_type_props_optional_table_indexer_type_level_scope_table_state(
94                        &props,
95                        Some(TableIndexer {
96                            index_type: key_ty,
97                            index_result_type: value_ty,
98                            is_read_only: false,
99                        }),
100                        TypeLevel::default(),
101                        scope,
102                        TableState::Free,
103                    ),
104                )
105            };
106            track_interior_free_type(scope, table_ty);
107
108            self.constraint_solver_unify(constraint, next_ty, table_ty);
109
110            let mut it = c.variables.iter();
111            if let Some(ty) = it.next() {
112                self.bind_not_null_constraint_type_id_type_id(constraint, *ty, key_ty);
113            }
114            if let Some(ty) = it.next() {
115                self.bind_not_null_constraint_type_id_type_id(constraint, *ty, value_ty);
116            }
117            for ty in it {
118                self.bind_not_null_constraint_type_id_type_id(constraint, *ty, unsafe {
119                    (*self.builtin_types).nilType
120                });
121            }
122
123            return true;
124        }
125
126        if unsafe { !get_type_id::<FunctionType>(next_ty).is_null() } {
127            let table_ty = if iterator.head.len() >= 2 {
128                iterator.head[1]
129            } else {
130                unsafe { (*self.builtin_types).nilType }
131            };
132
133            return self.try_dispatch_iterable_function(next_ty, table_ty, c, constraint);
134        }
135
136        self.try_dispatch_iterable_table(iterator.head[0], c, constraint, force)
137    }
138}