Skip to main content

luaur_analysis/methods/
constraint_solver_try_dispatch_constraint_solver_alt_d.rs

1use alloc::sync::Arc;
2
3use crate::enums::polarity::Polarity;
4use crate::functions::as_mutable_type::as_mutable_type_id;
5use crate::functions::as_mutable_type_pack::as_mutable_type_pack_id;
6use crate::functions::follow_type::follow_type_id;
7use crate::functions::follow_type_pack::follow_type_pack_id;
8use crate::functions::generalize::generalize;
9use crate::functions::generalize_type::generalize_type;
10use crate::functions::generalize_type_pack::generalize_type_pack;
11use crate::functions::get_mutable_type::get_mutable_type_id;
12use crate::functions::get_type_alt_j::get_type_id;
13use crate::functions::get_type_pack::get_type_pack_id;
14use crate::functions::is_known::is_known;
15use crate::functions::prune_unnecessary_generics::prune_unnecessary_generics;
16use crate::functions::seal_table::seal_table;
17use crate::records::blocked_type::BlockedType;
18use crate::records::code_too_complex::CodeTooComplex;
19use crate::records::constraint::Constraint;
20use crate::records::constraint_solver::ConstraintSolver;
21use crate::records::free_type::FreeType;
22use crate::records::free_type_pack::FreeTypePack;
23use crate::records::function_type::FunctionType;
24use crate::records::generalization_constraint::GeneralizationConstraint;
25use crate::records::generalization_params::GeneralizationParams;
26use crate::records::pending_expansion_type::PendingExpansionType;
27use crate::records::r#type::Type;
28use crate::records::table_type::TableType;
29use crate::records::type_pack_var::TypePackVar;
30use crate::type_aliases::type_pack_variant::TypePackVariant;
31use crate::type_aliases::type_variant::TypeVariant;
32
33impl ConstraintSolver {
34    pub fn try_dispatch_generalization_constraint_not_null_constraint(
35        &mut self,
36        c: &GeneralizationConstraint,
37        constraint: *const Constraint,
38    ) -> bool {
39        let generalized_type = unsafe { follow_type_id(c.generalized_type) };
40
41        if self.is_blocked_type_id(c.source_type) {
42            return self.block_type_id_not_null_constraint(c.source_type, constraint);
43        } else if unsafe { !get_type_id::<PendingExpansionType>(generalized_type).is_null() } {
44            return self.block_type_id_not_null_constraint(generalized_type, constraint);
45        }
46
47        let generalized_ty = generalize(
48            self.arena,
49            self.builtin_types,
50            unsafe { (*constraint).scope },
51            &mut self.generalized_types_ as *mut _,
52            c.source_type,
53            None,
54        );
55
56        if generalized_ty.is_none() {
57            self.report_error_type_error_data_location(CodeTooComplex::default().into(), unsafe {
58                &(*constraint).location
59            });
60        }
61
62        if let Some(generalized_ty) = generalized_ty {
63            prune_unnecessary_generics(
64                self.arena,
65                self.builtin_types,
66                unsafe { (*constraint).scope },
67                &mut self.generalized_types_ as *mut _,
68                generalized_ty,
69            );
70
71            if unsafe { !get_type_id::<BlockedType>(generalized_type).is_null() } {
72                self.bind_not_null_constraint_type_id_type_id(
73                    constraint,
74                    generalized_type,
75                    generalized_ty,
76                );
77            } else {
78                self.constraint_solver_unify(constraint, generalized_type, generalized_ty);
79            }
80
81            let fty =
82                unsafe { get_mutable_type_id::<FunctionType>(follow_type_id(generalized_type)) };
83            if !fty.is_null() && c.has_deprecated_attribute {
84                unsafe {
85                    (*fty).is_deprecated_function = true;
86                    (*fty).deprecated_info = Some(Arc::new(c.deprecated_info.clone()));
87                }
88            }
89        } else {
90            self.report_error_type_error_data_location(CodeTooComplex::default().into(), unsafe {
91                &(*constraint).location
92            });
93            self.bind_not_null_constraint_type_id_type_id(constraint, c.generalized_type, unsafe {
94                (*self.builtin_types).errorType
95            });
96        }
97
98        unsafe {
99            let scope = (*constraint).scope;
100
101            if let Some(interior_free_types) = (*scope).interior_free_types.as_ref() {
102                let interior_free_types = interior_free_types.clone();
103                for ty in interior_free_types {
104                    let ty = follow_type_id(ty);
105                    let free_ty = get_type_id::<FreeType>(ty);
106
107                    if !free_ty.is_null() {
108                        let params = GeneralizationParams {
109                            found_outside_functions: true,
110                            use_count: 1,
111                            polarity: (*free_ty).polarity,
112                        };
113                        let res =
114                            generalize_type(self.arena, self.builtin_types, scope, ty, &params);
115                        if res.resource_limits_exceeded {
116                            self.report_error_type_error_data_location(
117                                CodeTooComplex::default().into(),
118                                &(*scope).location,
119                            );
120                        }
121                    } else if !get_type_id::<TableType>(ty).is_null() {
122                        seal_table(scope, ty);
123                    }
124
125                    self.unblock_type_id_location(ty, (*constraint).location);
126                }
127            }
128
129            if let Some(interior_free_type_packs) = (*scope).interior_free_type_packs.as_ref() {
130                let interior_free_type_packs = interior_free_type_packs.clone();
131                for tp in interior_free_type_packs {
132                    let tp = follow_type_pack_id(tp);
133                    let free_tp = get_type_pack_id::<FreeTypePack>(tp);
134
135                    if !free_tp.is_null() {
136                        let params = GeneralizationParams {
137                            found_outside_functions: true,
138                            use_count: 1,
139                            polarity: (*free_tp).polarity,
140                        };
141                        luaur_common::macros::luau_assert::LUAU_ASSERT!(is_known(params.polarity));
142                        generalize_type_pack(self.arena, self.builtin_types, scope, tp, &params);
143                    }
144                }
145            }
146
147            if c.no_generics {
148                let ft = get_mutable_type_id::<FunctionType>(c.source_type);
149                if !ft.is_null() {
150                    for gen in (*ft).generics.iter().copied() {
151                        (*as_mutable_type_id(gen)).ty =
152                            TypeVariant::Bound((*self.builtin_types).unknownType);
153                    }
154                    (*ft).generics.clear();
155
156                    for gen in (*ft).generic_packs.iter().copied() {
157                        (*as_mutable_type_pack_id(gen)).ty =
158                            TypePackVariant::Bound((*self.builtin_types).unknownTypePack);
159                    }
160                    (*ft).generic_packs.clear();
161                }
162            }
163        }
164
165        true
166    }
167}