luaur_analysis/methods/
unifier_try_unify_scalar_shape.rs1use crate::enums::normalization_result::NormalizationResult;
3use crate::enums::table_state::TableState;
4use crate::functions::get_metatable_type::get_metatable_type_id_not_null_builtin_types;
5use crate::functions::has_unification_too_complex::has_unification_too_complex;
6use crate::records::r#type::Type;
7use crate::records::table_type::TableType;
8use crate::records::type_error::TypeError;
9use crate::records::type_mismatch::TypeMismatch;
10use crate::records::unifier::Unifier;
11use crate::type_aliases::type_error_data::TypeErrorData;
12use crate::type_aliases::type_id::TypeId;
13use crate::type_aliases::type_variant::TypeVariant;
14use alloc::string::String;
15use alloc::sync::Arc;
16
17impl Unifier {
18 pub fn unifier_try_unify_scalar_shape(
20 &mut self,
21 mut sub_ty: TypeId,
22 mut super_ty: TypeId,
23 reversed: bool,
24 ) {
25 let osub_ty = sub_ty;
26 let osuper_ty = super_ty;
27
28 if self.check_inhabited
30 && unsafe { (*self.normalizer).is_inhabited_type_id(sub_ty) }
31 == NormalizationResult::False
32 {
33 return;
34 }
35
36 if reversed {
37 core::mem::swap(&mut sub_ty, &mut super_ty);
38 }
39
40 let super_table = self.log.txn_log_get_mutable::<TableType, TypeId>(super_ty);
41
42 if super_table.is_null() || unsafe { (*super_table).state } != TableState::Free {
43 let context = self.unifier_mismatch_context();
44 self.report_error_location_type_error_data(
45 self.location,
46 TypeErrorData::TypeMismatch(TypeMismatch {
47 wanted_type: osuper_ty,
48 given_type: osub_ty,
49 reason: String::new(),
50 error: None,
51 context,
52 }),
53 );
54 return;
55 }
56
57 if let Some(metatable) =
60 get_metatable_type_id_not_null_builtin_types(sub_ty, unsafe { &*self.builtin_types })
61 {
62 let mttv = self.log.txn_log_get::<TableType, TypeId>(metatable);
63 if mttv.is_null() {
64 self.scalar_shape_fail(osuper_ty, osub_ty, None);
65 }
66
67 if let Some(prop) = unsafe { (*mttv).props.get("__index") } {
68 let ty = prop.type_deprecated();
69 let mut child = self.unifier_make_child_unifier();
70 child.try_unify_type_id_type_id_bool_bool_literal_properties(
71 ty, super_ty, false, false, None,
72 );
73
74 let new_super_ty = child.log.follow_type_id(super_ty);
78
79 if super_ty != new_super_ty
80 && self
81 .can_unify_type_id_type_id(sub_ty, new_super_ty)
82 .is_empty()
83 {
84 self.log
85 .replace_type_id_t(super_ty, Type::new(TypeVariant::Bound(sub_ty)));
86 return;
87 }
88
89 if let Some(e) = has_unification_too_complex(&child.errors) {
90 self.report_error_type_error(e);
91 } else if !child.errors.is_empty() {
92 let first = child.errors[0].clone();
93 self.scalar_shape_fail(osuper_ty, osub_ty, Some(first));
94 }
95
96 let child_errors_empty = child.errors.is_empty();
97 self.log.concat(child.log);
98
99 if child_errors_empty {
102 self.log
103 .replace_type_id_t(super_ty, Type::new(TypeVariant::Bound(sub_ty)));
104 }
105
106 return;
107 } else {
108 self.scalar_shape_fail(osuper_ty, osub_ty, None);
109 return;
110 }
111 }
112
113 let context = self.unifier_mismatch_context();
114 self.report_error_location_type_error_data(
115 self.location,
116 TypeErrorData::TypeMismatch(TypeMismatch {
117 wanted_type: osuper_ty,
118 given_type: osub_ty,
119 reason: String::new(),
120 error: None,
121 context,
122 }),
123 );
124 }
125
126 fn scalar_shape_fail(&mut self, osuper_ty: TypeId, osub_ty: TypeId, e: Option<TypeError>) {
128 let reason = String::from("The given type's metatable does not satisfy the requirements.");
129 let context = self.unifier_mismatch_context();
130 self.report_error_location_type_error_data(
131 self.location,
132 TypeErrorData::TypeMismatch(TypeMismatch {
133 wanted_type: osuper_ty,
134 given_type: osub_ty,
135 reason,
136 error: e.map(Arc::new),
137 context,
138 }),
139 );
140 }
141}