Skip to main content

luaur_analysis/functions/
intersect_one_with_intersection.rs

1use crate::enums::inhabited::Inhabited;
2use crate::enums::relation::Relation;
3use crate::functions::follow_type::follow_type_id;
4use crate::functions::get_type_alt_j::get_type_id;
5use crate::functions::relate_simplify_alt_b::relate_type_id_type_id;
6use crate::records::intersection_type::IntersectionType;
7use crate::records::type_ids::TypeIds;
8use crate::records::type_simplifier::TypeSimplifier;
9use crate::type_aliases::type_id::TypeId;
10
11pub fn intersect_one_with_intersection(
12    simplifier: &mut TypeSimplifier,
13    source: &mut TypeIds,
14    dest: &mut TypeIds,
15    candidate: TypeId,
16) -> Inhabited {
17    // `get<T>` requires a followed type (it asserts the argument is not a BoundType).
18    // The C++ pipeline guarantees the candidate is followed at this point (TypeIds
19    // entries are followed on insert); a recursed sub-part of an IntersectionType is
20    // not necessarily followed, so we follow here to preserve that invariant.
21    let candidate = unsafe { follow_type_id(candidate) };
22
23    if dest.count(candidate) > 0 {
24        return Inhabited::Yes;
25    }
26
27    if let Some(itv) = unsafe { get_type_id::<IntersectionType>(candidate).as_ref() } {
28        for &sub_part in &itv.parts {
29            if intersect_one_with_intersection(simplifier, source, dest, sub_part) == Inhabited::No
30            {
31                return Inhabited::No;
32            }
33        }
34
35        return Inhabited::Yes;
36    }
37
38    if source.empty() {
39        dest.insert_type_id(candidate);
40        return Inhabited::Yes;
41    }
42    for i in 0..source.size() {
43        let ty = unsafe { *source.order.as_ptr().add(i) };
44        match relate_type_id_type_id(candidate, ty) {
45            Relation::Disjoint => return Inhabited::No,
46            Relation::Subset => dest.insert_type_id(candidate),
47            Relation::Coincident | Relation::Superset => dest.insert_type_id(ty),
48            Relation::Intersects => {
49                if let Some(simplified) = simplifier.basic_intersect(candidate, ty) {
50                    dest.insert_type_id(simplified);
51                } else {
52                    dest.insert_type_id(candidate);
53                    dest.insert_type_id(ty);
54                }
55            }
56        }
57    }
58    Inhabited::Yes
59}