Skip to main content

luaur_analysis/functions/
merge_reasonings.rs

1use crate::enums::subtyping_variance::SubtypingVariance;
2use crate::records::path_hash::PathHash;
3use crate::records::subtyping_reasoning::SubtypingReasoning;
4use crate::records::subtyping_reasoning_hash::SubtypingReasoningHash;
5use crate::records::subtyping_result::SubtypingResult;
6use crate::type_aliases::path::Path;
7use crate::type_aliases::subtyping_reasonings::SubtypingReasonings;
8use luaur_common::records::dense_hash_table::{DenseDefault, DenseHasher};
9
10impl PartialEq for SubtypingReasoning {
11    fn eq(&self, other: &Self) -> bool {
12        self.operator_eq(other)
13    }
14}
15
16impl Eq for SubtypingReasoning {}
17
18impl DenseHasher<SubtypingReasoning> for SubtypingReasoningHash {
19    fn hash(&self, r: &SubtypingReasoning) -> usize {
20        PathHash.operator_call_6(&r.sub_path)
21            ^ (PathHash.operator_call_6(&r.super_path) << 1)
22            ^ ((r.variance as usize) << 1)
23            ^ ((r.is_property_modifier_violation as usize) << 2)
24    }
25}
26
27pub(crate) fn k_empty_reasoning() -> SubtypingReasoning {
28    SubtypingReasoning {
29        sub_path: Path::default(),
30        super_path: Path::default(),
31        variance: SubtypingVariance::Invalid,
32        is_property_modifier_violation: false,
33    }
34}
35
36impl Default for SubtypingResult {
37    fn default() -> Self {
38        SubtypingResult {
39            is_subtype: false,
40            normalization_too_complex: false,
41            is_cacheable: true,
42            is_error_suppressing: false,
43            errors: Default::default(),
44            reasoning: SubtypingReasonings::new(k_empty_reasoning()),
45            assumed_constraints: Default::default(),
46            generic_bounds_mismatches: Default::default(),
47        }
48    }
49}
50
51impl DenseDefault for SubtypingResult {
52    fn dense_default() -> Self {
53        SubtypingResult::default()
54    }
55}
56
57pub fn merge_reasonings(a: &SubtypingReasonings, b: &SubtypingReasonings) -> SubtypingReasonings {
58    let mut result = SubtypingReasonings::new(k_empty_reasoning());
59
60    for r in a.iter() {
61        if r.variance == SubtypingVariance::Invariant {
62            result.insert(r.clone());
63        } else if r.variance == SubtypingVariance::Covariant
64            || r.variance == SubtypingVariance::Contravariant
65        {
66            let inverse_reasoning = SubtypingReasoning {
67                sub_path: r.sub_path.clone(),
68                super_path: r.super_path.clone(),
69                variance: if r.variance == SubtypingVariance::Covariant {
70                    SubtypingVariance::Contravariant
71                } else {
72                    SubtypingVariance::Covariant
73                },
74                is_property_modifier_violation: false,
75            };
76
77            if b.contains(&inverse_reasoning) {
78                result.insert(SubtypingReasoning {
79                    sub_path: r.sub_path.clone(),
80                    super_path: r.super_path.clone(),
81                    variance: SubtypingVariance::Invariant,
82                    is_property_modifier_violation: false,
83                });
84            } else {
85                result.insert(r.clone());
86            }
87        }
88
89        if result.size() >= luaur_common::FInt::LuauSubtypingReasoningLimit.get() as usize {
90            return result;
91        }
92    }
93
94    for r in b.iter() {
95        if r.variance == SubtypingVariance::Invariant {
96            result.insert(r.clone());
97        } else if r.variance == SubtypingVariance::Covariant
98            || r.variance == SubtypingVariance::Contravariant
99        {
100            let inverse_reasoning = SubtypingReasoning {
101                sub_path: r.sub_path.clone(),
102                super_path: r.super_path.clone(),
103                variance: if r.variance == SubtypingVariance::Covariant {
104                    SubtypingVariance::Contravariant
105                } else {
106                    SubtypingVariance::Covariant
107                },
108                is_property_modifier_violation: false,
109            };
110
111            if a.contains(&inverse_reasoning) {
112                result.insert(SubtypingReasoning {
113                    sub_path: r.sub_path.clone(),
114                    super_path: r.super_path.clone(),
115                    variance: SubtypingVariance::Invariant,
116                    is_property_modifier_violation: false,
117                });
118            } else {
119                result.insert(r.clone());
120            }
121        }
122
123        if result.size() >= luaur_common::FInt::LuauSubtypingReasoningLimit.get() as usize {
124            return result;
125        }
126    }
127
128    result
129}