Skip to main content

luaur_analysis/methods/
unifier_try_unify_with_metatable.rs

1use 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}