1use crate::Type;
6use crate::cache::TypeCache;
7use crate::type_kind::TypeKind;
8
9impl Type {
10 pub(crate) fn do_compatible_with(&self, other: &Self, type_cache: &mut TypeCache) -> bool {
11 if self.id == other.id {
12 return true;
13 }
14
15 if matches!(&*other.kind, TypeKind::Never) {
17 return true;
18 }
19
20 if matches!(&*self.kind, TypeKind::Never) {
22 return true;
23 }
24
25 match (&*self.kind, &*other.kind) {
26 (TypeKind::Int, TypeKind::Int) => true,
28 (TypeKind::Float, TypeKind::Float) => true,
29 (TypeKind::Bool, TypeKind::Bool) => true,
30 (TypeKind::Codepoint, TypeKind::Codepoint) => true,
31 (TypeKind::StringView(..), TypeKind::StringView(..)) => true,
32 (TypeKind::Unit, TypeKind::Unit) => true,
33
34 (TypeKind::Optional(a), TypeKind::Optional(b)) => type_cache.compatible_with(a, b),
37
38 (TypeKind::VecStorage(a, _), TypeKind::VecStorage(b, _)) => {
39 type_cache.compatible_with(a, b)
40 }
41 (TypeKind::SparseStorage(a, _), TypeKind::SparseStorage(b, _)) => {
42 type_cache.compatible_with(a, b)
43 }
44 (TypeKind::QueueStorage(a, _), TypeKind::QueueStorage(b, _)) => {
45 type_cache.compatible_with(a, b)
46 }
47
48 (TypeKind::StackStorage(a, _), TypeKind::StackStorage(b, _)) => {
49 type_cache.compatible_with(a, b)
50 }
51
52 (TypeKind::MapStorage(a_key, a_value, _), TypeKind::MapStorage(b_key, b_value, _)) => {
53 type_cache.compatible_with(a_key, b_key)
54 && type_cache.compatible_with(a_value, b_value)
55 }
56
57 (
58 TypeKind::GridStorage(a, rows_a, cols_a),
59 TypeKind::GridStorage(b, rows_b, cols_b),
60 ) => rows_a >= rows_b && cols_a >= cols_b && type_cache.compatible_with(a, b),
61
62 (TypeKind::SliceView(a), TypeKind::SliceView(b)) => type_cache.compatible_with(a, b),
63 (TypeKind::SparseView(a), TypeKind::SparseView(b)) => type_cache.compatible_with(a, b),
64 (TypeKind::QueueView(a), TypeKind::QueueView(b)) => type_cache.compatible_with(a, b),
65 (TypeKind::StackView(a), TypeKind::StackView(b)) => type_cache.compatible_with(a, b),
66 (TypeKind::DynamicLengthVecView(a), TypeKind::DynamicLengthVecView(b)) => {
67 type_cache.compatible_with(a, b)
68 }
69 (
70 TypeKind::DynamicLengthMapView(a_key, a_value),
71 TypeKind::DynamicLengthMapView(b_key, b_value),
72 ) => {
73 type_cache.compatible_with(a_key, b_key)
74 && type_cache.compatible_with(a_value, b_value)
75 }
76
77 (
78 TypeKind::FixedCapacityAndLengthArray(a, size_a),
79 TypeKind::FixedCapacityAndLengthArray(b, size_b),
80 ) => {
81 size_a == size_b && type_cache.compatible_with(a, b) }
83
84 (TypeKind::Tuple(elems_a), TypeKind::Tuple(elems_b)) => {
85 elems_a.len() == elems_b.len() }
87
88 (TypeKind::AnonymousStruct(anon_a), TypeKind::AnonymousStruct(anon_b)) => {
89 anon_a.field_name_sorted_fields.len() == anon_b.field_name_sorted_fields.len()
90 && anon_a
91 .field_name_sorted_fields
92 .keys()
93 .all(|key| anon_b.field_name_sorted_fields.contains_key(key))
94 }
95
96 (TypeKind::NamedStruct(named_a), TypeKind::NamedStruct(named_b)) => {
97 named_a.assigned_name == named_b.assigned_name
98 && type_cache
99 .compatible_with(&named_a.anon_struct_type, &named_b.anon_struct_type)
100 }
101
102 (TypeKind::Enum(enum_a), TypeKind::Enum(enum_b)) => {
103 enum_a.assigned_name == enum_b.assigned_name
104 && enum_a.instantiated_type_parameters.len()
105 == enum_b.instantiated_type_parameters.len()
106 }
107
108 (TypeKind::Function(sig_a), TypeKind::Function(sig_b)) => {
109 sig_a.parameters.len() == sig_b.parameters.len()
110 }
111
112 _ => self.compatible_with_storage_and_view(other, type_cache),
114 }
115 }
116
117 #[must_use]
118 pub fn compatible_with_storage_and_view(
119 &self,
120 other_view: &Self,
121 type_cache: &mut TypeCache,
122 ) -> bool {
123 if matches!(&*self.kind, TypeKind::StringView(..))
124 && matches!(
125 &*other_view.kind,
126 TypeKind::VecStorage(inner_type, ..) | TypeKind::DynamicLengthVecView(inner_type)
127 )
128 {
129 match &*other_view.kind {
130 TypeKind::VecStorage(inner_type, ..)
131 | TypeKind::DynamicLengthVecView(inner_type) => {
132 return false;
134 }
135 _ => {}
136 }
137 }
138
139 if matches!(&*self.kind, TypeKind::StringStorage(..))
140 && matches!(&*other_view.kind, TypeKind::StringView(inner_type, ..))
141 {
142 }
144
145 let left_kind = self.lowest_common_denominator_vec_like_view();
146 let right_kind = other_view.lowest_common_denominator_vec_like_view();
147 if left_kind.is_some() && right_kind.is_some() {
148 let left = left_kind.unwrap();
149 let right = right_kind.unwrap();
150 match (left, right) {
151 (TypeKind::SliceView(a), TypeKind::SliceView(b)) => {
152 type_cache.compatible_with(&a, &b)
153 }
154 (TypeKind::DynamicLengthVecView(a), TypeKind::DynamicLengthVecView(b)) => {
155 type_cache.compatible_with(&a, &b)
156 }
157 _ => false,
158 }
159 } else {
160 match (&*self.kind, &*other_view.kind) {
161 (
162 TypeKind::MapStorage(key_a, value_a, _),
163 TypeKind::DynamicLengthMapView(key_b, value_b),
164 )
165 | (
166 TypeKind::DynamicLengthMapView(key_a, value_a),
167 TypeKind::MapStorage(key_b, value_b, _),
168 ) => {
169 type_cache.compatible_with(key_a, key_b)
170 && type_cache.compatible_with(value_a, value_b)
171 }
172 _ => false,
173 }
174 }
175 }
176
177 #[must_use]
179 pub fn lowest_common_denominator_vec_like_view(&self) -> Option<TypeKind> {
180 match &*self.kind {
181 TypeKind::FixedCapacityAndLengthArray(inner, _)
182 | TypeKind::QueueStorage(inner, _)
183 | TypeKind::StackStorage(inner, _)
184 | TypeKind::SparseStorage(inner, _)
185 | TypeKind::StringStorage(inner, _, _)
186 | TypeKind::VecStorage(inner, _) => Some(TypeKind::SliceView(inner.clone())),
187
188 TypeKind::SliceView(inner)
189 | TypeKind::QueueView(inner)
190 | TypeKind::StackView(inner)
191 | TypeKind::SparseView(inner)
192 | TypeKind::StringView(inner, _)
193 | TypeKind::DynamicLengthVecView(inner) => Some(TypeKind::SliceView(inner.clone())),
194
195 _ => None,
196 }
197 }
198
199 #[must_use]
200 pub fn strict_compatible_with_capacity(&self, other: &Self) -> bool {
201 match (&*self.kind, &*other.kind) {
202 (TypeKind::VecStorage(_, cap_a), TypeKind::VecStorage(_, cap_b)) => cap_a == cap_b,
203 (TypeKind::SparseStorage(_, cap_a), TypeKind::SparseStorage(_, cap_b)) => {
204 cap_a == cap_b
205 }
206 (TypeKind::QueueStorage(_, cap_a), TypeKind::QueueStorage(_, cap_b)) => cap_a == cap_b,
207 (TypeKind::StackStorage(_, cap_a), TypeKind::StackStorage(_, cap_b)) => cap_a == cap_b,
208 (TypeKind::MapStorage(_, _, cap_a), TypeKind::MapStorage(_, _, cap_b)) => {
209 cap_a == cap_b
210 }
211 (
212 TypeKind::GridStorage(_, rows_a, cols_a),
213 TypeKind::GridStorage(_, rows_b, cols_b),
214 ) => rows_a == rows_b && cols_a == cols_b,
215 _ => self.id == other.id,
217 }
218 }
219}