luaur_analysis/methods/
subtyping_unifier_dispatch_one_constraint.rs1use crate::enums::occurs_check_result::OccursCheckResult;
4use crate::enums::unify_result::UnifyResult;
5use crate::functions::as_mutable_type_pack::as_mutable_type_pack_id;
6use crate::functions::emplace_type_pack::emplace_type_pack;
7use crate::functions::follow_type::follow_type_id;
8use crate::functions::follow_type_pack::follow_type_pack_id;
9use crate::functions::get_2::get2;
10use crate::functions::get_mutable_type::get_mutable_type_id;
11use crate::functions::get_type_pack::get_type_pack_id;
12use crate::functions::is_blocked_type_utils::is_blocked;
13use crate::functions::occurs_check_type_utils_alt_b::occurs_check_type_pack_id_type_pack_id;
14use crate::functions::simplify_intersection_simplify::simplify_intersection;
15use crate::functions::simplify_union::simplify_union;
16use crate::records::constraint::Constraint;
17use crate::records::free_type::FreeType;
18use crate::records::free_type_pack::FreeTypePack;
19use crate::records::pack_subtype_constraint::PackSubtypeConstraint;
20use crate::records::subtype_constraint::SubtypeConstraint;
21use crate::records::subtyping_unifier::SubtypingUnifier;
22use crate::records::table_indexer::TableIndexer;
23use crate::records::table_type::TableType;
24use crate::type_aliases::constraint_v::{ConstraintV, ConstraintVMember};
25use crate::type_aliases::type_pack_variant::TypePackVariant;
26use crate::type_aliases::upper_bounds::UpperBounds;
27use luaur_common::macros::luau_assert::LUAU_ASSERT;
28use luaur_common::FFlag;
29
30impl SubtypingUnifier {
31 pub fn dispatch_one_constraint(
32 &self,
33 constraint: *const Constraint,
34 cv: &ConstraintV,
35 upper_bound_contributors: &mut UpperBounds,
36 ) -> (UnifyResult, bool) {
37 let builtin_types = self.builtin_types;
38 let arena = self.arena;
39
40 if let Some(sc) = SubtypeConstraint::get_if(cv) {
41 let sub_ty = unsafe { follow_type_id(sc.sub_type) };
42 let super_ty = unsafe { follow_type_id(sc.super_type) };
43
44 LUAU_ASSERT!(self.can_be_unified(sub_ty) || self.can_be_unified(super_ty));
45
46 if is_blocked(sub_ty) || is_blocked(super_ty) {
47 return (UnifyResult::Ok, false);
48 }
49
50 let super_free_ty = unsafe { get_mutable_type_id::<FreeType>(super_ty) };
51 if !super_free_ty.is_null() {
52 let lower = unsafe { (*super_free_ty).lower_bound };
53 let result = simplify_union(builtin_types, arena, sub_ty, lower).result;
54 unsafe {
55 (*super_free_ty).lower_bound = result;
56 }
57 }
58
59 let sub_free_type = unsafe { get_mutable_type_id::<FreeType>(sub_ty) };
60 if !sub_free_type.is_null() {
61 let upper = unsafe { (*sub_free_type).upper_bound };
62 let result = simplify_intersection(builtin_types, arena, upper, super_ty).result;
63 unsafe {
64 (*sub_free_type).upper_bound = result;
65 }
66 let location = unsafe { (*constraint).location };
67 upper_bound_contributors
68 .get_or_insert(sub_ty)
69 .push((location, super_ty));
70 }
71
72 let pair = get2::<TableType, TableType, _>(sub_ty, super_ty);
74 if !pair.first.is_null() && unsafe { (*pair.first).indexer }.is_none() {
75 let super_indexer = unsafe { (*pair.second).indexer.clone() }.unwrap();
76 let sub_table = unsafe { get_mutable_type_id::<TableType>(sub_ty) };
77 unsafe {
78 (*sub_table).indexer = Some(TableIndexer {
79 index_type: super_indexer.index_type,
80 index_result_type: super_indexer.index_result_type,
81 is_read_only: false,
82 });
83 }
84 }
85 } else if let Some(psc) = PackSubtypeConstraint::get_if(cv) {
86 let sub_tp = unsafe { follow_type_pack_id(psc.sub_pack) };
87 let super_tp = unsafe { follow_type_pack_id(psc.super_pack) };
88 let error_pack = unsafe { (*builtin_types).errorTypePack };
100
101 if !unsafe { get_type_pack_id::<FreeTypePack>(sub_tp) }.is_null() {
102 if FFlag::LuauOccursCheckForAllBindings.get() {
103 if OccursCheckResult::Fail
104 == occurs_check_type_pack_id_type_pack_id(sub_tp, super_tp)
105 {
106 emplace_type_pack(
107 unsafe { as_mutable_type_pack_id(sub_tp) },
108 TypePackVariant::Bound(error_pack),
109 );
110 return (UnifyResult::OccursCheckFailed, true);
111 }
112 } else {
113 if OccursCheckResult::Fail == self.occurs_check_DEPRECATED(sub_tp, super_tp) {
114 emplace_type_pack(
115 unsafe { as_mutable_type_pack_id(sub_tp) },
116 TypePackVariant::Bound(error_pack),
117 );
118 return (UnifyResult::OccursCheckFailed, true);
119 }
120 }
121 emplace_type_pack(
122 unsafe { as_mutable_type_pack_id(sub_tp) },
123 TypePackVariant::Bound(super_tp),
124 );
125 return (UnifyResult::Ok, true);
126 }
127
128 if !unsafe { get_type_pack_id::<FreeTypePack>(super_tp) }.is_null() {
129 if FFlag::LuauOccursCheckForAllBindings.get() {
130 if OccursCheckResult::Fail
131 == occurs_check_type_pack_id_type_pack_id(super_tp, sub_tp)
132 {
133 emplace_type_pack(
134 unsafe { as_mutable_type_pack_id(super_tp) },
135 TypePackVariant::Bound(error_pack),
136 );
137 return (UnifyResult::OccursCheckFailed, true);
138 }
139 } else {
140 if OccursCheckResult::Fail == self.occurs_check_DEPRECATED(super_tp, sub_tp) {
141 emplace_type_pack(
142 unsafe { as_mutable_type_pack_id(super_tp) },
143 TypePackVariant::Bound(error_pack),
144 );
145 return (UnifyResult::OccursCheckFailed, true);
146 }
147 }
148
149 emplace_type_pack(
150 unsafe { as_mutable_type_pack_id(super_tp) },
151 TypePackVariant::Bound(sub_tp),
152 );
153 return (UnifyResult::Ok, true);
154 }
155 } else {
156 LUAU_ASSERT!(false); return (UnifyResult::Ok, false);
158 }
159
160 (UnifyResult::Ok, true)
161 }
162}