luaur_analysis/methods/
unifier_try_unify_with_metatable.rs1use crate::functions::get_mutable_type::get_mutable_type_id;
2use crate::functions::get_type_alt_j::get_type_id;
3use crate::functions::has_unification_too_complex::has_unification_too_complex;
4use crate::records::any_type::AnyType;
5use crate::records::metatable_type::MetatableType;
6use crate::records::table_type::TableType;
7use crate::records::type_mismatch::TypeMismatch;
8use crate::records::unifier::Unifier;
9use crate::type_aliases::error_type::ErrorType;
10use crate::type_aliases::type_error_data::TypeErrorData;
11use crate::type_aliases::type_id::TypeId;
12use alloc::string::String;
13use alloc::sync::Arc;
14
15impl Unifier {
16 pub fn unifier_try_unify_with_metatable(
17 &mut self,
18 sub_ty: TypeId,
19 super_ty: TypeId,
20 reversed: bool,
21 ) {
22 let super_metatable = unsafe { get_type_id::<MetatableType>(super_ty) };
23 if super_metatable.is_null() {
24 self.ice_string("tryUnifyMetatable invoked with non-metatable Type");
25 return;
26 }
27
28 let wanted = if reversed { sub_ty } else { super_ty };
29 let given = if reversed { super_ty } else { sub_ty };
30
31 if let Some(sub_metatable) =
32 unsafe { get_mutable_type_id::<MetatableType>(sub_ty).as_mut() }
33 {
34 let mut inner_state = self.unifier_make_child_unifier();
35 inner_state.try_unify_type_id_type_id_bool_bool_literal_properties(
36 sub_metatable.table,
37 unsafe { (*super_metatable).table },
38 false,
39 false,
40 None,
41 );
42 inner_state.try_unify_type_id_type_id_bool_bool_literal_properties(
43 sub_metatable.metatable,
44 unsafe { (*super_metatable).metatable },
45 false,
46 false,
47 None,
48 );
49
50 if let Some(e) = has_unification_too_complex(&inner_state.errors) {
51 self.report_error_type_error(e);
52 } else if !inner_state.errors.is_empty() {
53 let context = self.unifier_mismatch_context();
54 self.report_error_location_type_error_data(
55 self.location,
56 TypeErrorData::TypeMismatch(TypeMismatch {
57 wanted_type: wanted,
58 given_type: given,
59 reason: String::new(),
60 error: Some(Arc::new(inner_state.errors[0].clone())),
61 context,
62 }),
63 );
64 }
65
66 self.log.concat(inner_state.log);
67 self.failure |= inner_state.failure;
68 } else if let Some(sub_table) = unsafe { get_mutable_type_id::<TableType>(sub_ty).as_mut() }
69 {
70 match sub_table.state {
71 crate::enums::table_state::TableState::Free => {
72 self.try_unify_type_id_type_id_bool_bool_literal_properties(
73 sub_ty,
74 unsafe { (*super_metatable).table },
75 false,
76 false,
77 None,
78 );
79 self.log.bind_table(sub_ty, Some(super_ty));
80 }
81 crate::enums::table_state::TableState::Sealed
82 | crate::enums::table_state::TableState::Unsealed
83 | crate::enums::table_state::TableState::Generic => {
84 let context = self.unifier_mismatch_context();
85 self.report_error_location_type_error_data(
86 self.location,
87 TypeErrorData::TypeMismatch(TypeMismatch {
88 wanted_type: wanted,
89 given_type: given,
90 reason: String::new(),
91 error: None,
92 context,
93 }),
94 );
95 }
96 }
97 } else if !unsafe { get_mutable_type_id::<AnyType>(sub_ty) }.is_null()
98 || !unsafe { get_mutable_type_id::<ErrorType>(sub_ty) }.is_null()
99 {
100 } else {
101 let context = self.unifier_mismatch_context();
102 self.report_error_location_type_error_data(
103 self.location,
104 TypeErrorData::TypeMismatch(TypeMismatch {
105 wanted_type: wanted,
106 given_type: given,
107 reason: String::new(),
108 error: None,
109 context,
110 }),
111 );
112 }
113 }
114}