luaur_analysis/functions/
merge_reasonings.rs1use 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}