Skip to main content

luaur_analysis/methods/
unifier_occurs_check_unifier.rs

1//! Source: `Analysis/src/Unifier.cpp` (Unifier::occursCheck(TypeId,...), L2606-2642)
2use crate::functions::get_type_alt_j::get_type_id;
3use crate::records::intersection_type::IntersectionType;
4use crate::records::occurs_check_failed::OccursCheckFailed;
5use crate::records::r#type::Type;
6use crate::records::unifier::Unifier;
7use crate::records::union_type::UnionType;
8use crate::type_aliases::type_error_data::TypeErrorData;
9use crate::type_aliases::type_id::TypeId;
10use crate::type_aliases::type_variant::TypeVariant;
11
12impl Unifier {
13    /// `bool Unifier::occursCheck(TypeId needle, TypeId haystack, bool reversed)`
14    pub fn occurs_check_type_id_type_id_bool(
15        &mut self,
16        needle: TypeId,
17        haystack: TypeId,
18        reversed: bool,
19    ) -> bool {
20        let shared_state = unsafe { &mut *self.shared_state };
21        shared_state.temp_seen_ty.clear();
22
23        let occurs = self.occurs_check_dense_hash_set_type_id_type_id_type_id(
24            &mut shared_state.temp_seen_ty,
25            needle,
26            haystack,
27        );
28
29        if occurs {
30            let mut inner_state = self.unifier_make_child_unifier();
31            let ut = unsafe { get_type_id::<UnionType>(haystack) };
32            let it = unsafe { get_type_id::<IntersectionType>(haystack) };
33
34            if !ut.is_null() {
35                if reversed {
36                    inner_state.unifier_try_unify_union_with_type(haystack, ut, needle);
37                } else {
38                    inner_state
39                        .unifier_try_unify_type_with_union(needle, haystack, ut, false, false);
40                }
41            } else if !it.is_null() {
42                if reversed {
43                    inner_state.unifier_try_unify_intersection_with_type(
44                        haystack, it, needle, false, false,
45                    );
46                } else {
47                    inner_state.unifier_try_unify_type_with_intersection(needle, haystack, it);
48                }
49            } else {
50                inner_state.failure = true;
51            }
52
53            if inner_state.failure {
54                self.report_error_location_type_error_data(
55                    self.location,
56                    TypeErrorData::OccursCheckFailed(OccursCheckFailed::default()),
57                );
58                // C++: log.replace(needle, BoundType{builtinTypes->errorType});
59                let error_ty = unsafe { (*self.builtin_types).errorType };
60                self.log
61                    .replace_type_id_t(needle, Type::new(TypeVariant::Bound(error_ty)));
62            }
63        }
64
65        occurs
66    }
67}