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::String(..), TypeKind::String(..)) => 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 && named_a.instantiated_type_parameters.len()
99 == named_b.instantiated_type_parameters.len()
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 let left_kind = self.lowest_common_denominator_vec_like_view();
124 let right_kind = other_view.lowest_common_denominator_vec_like_view();
125 if left_kind.is_some() && right_kind.is_some() {
126 let left = left_kind.unwrap();
127 let right = right_kind.unwrap();
128 match (left, right) {
129 (TypeKind::SliceView(a), TypeKind::SliceView(b)) => {
130 type_cache.compatible_with(&a, &b)
131 }
132 (TypeKind::DynamicLengthVecView(a), TypeKind::DynamicLengthVecView(b)) => {
133 type_cache.compatible_with(&a, &b)
134 }
135 _ => false,
136 }
137 } else {
138 match (&*self.kind, &*other_view.kind) {
139 (
140 TypeKind::MapStorage(key_a, value_a, _),
141 TypeKind::DynamicLengthMapView(key_b, value_b),
142 )
143 | (
144 TypeKind::DynamicLengthMapView(key_a, value_a),
145 TypeKind::MapStorage(key_b, value_b, _),
146 ) => {
147 type_cache.compatible_with(key_a, key_b)
148 && type_cache.compatible_with(value_a, value_b)
149 }
150 _ => false,
151 }
152 }
153 }
154
155 #[must_use]
157 pub fn lowest_common_denominator_vec_like_view(&self) -> Option<TypeKind> {
158 match &*self.kind {
159 TypeKind::FixedCapacityAndLengthArray(inner, _)
160 | TypeKind::QueueStorage(inner, _)
161 | TypeKind::StackStorage(inner, _)
162 | TypeKind::SparseStorage(inner, _)
163 | TypeKind::StringStorage(inner, _, _)
164 | TypeKind::VecStorage(inner, _) => Some(TypeKind::SliceView(inner.clone())),
165
166 TypeKind::SliceView(inner)
167 | TypeKind::QueueView(inner)
168 | TypeKind::StackView(inner)
169 | TypeKind::SparseView(inner)
170 | TypeKind::String(inner, _)
171 | TypeKind::DynamicLengthVecView(inner) => Some(TypeKind::SliceView(inner.clone())),
172
173 _ => None,
174 }
175 }
176
177 #[must_use]
178 pub fn strict_compatible_with_capacity(&self, other: &Self) -> bool {
179 match (&*self.kind, &*other.kind) {
180 (TypeKind::VecStorage(_, cap_a), TypeKind::VecStorage(_, cap_b)) => cap_a == cap_b,
181 (TypeKind::SparseStorage(_, cap_a), TypeKind::SparseStorage(_, cap_b)) => {
182 cap_a == cap_b
183 }
184 (TypeKind::QueueStorage(_, cap_a), TypeKind::QueueStorage(_, cap_b)) => cap_a == cap_b,
185 (TypeKind::StackStorage(_, cap_a), TypeKind::StackStorage(_, cap_b)) => cap_a == cap_b,
186 (TypeKind::MapStorage(_, _, cap_a), TypeKind::MapStorage(_, _, cap_b)) => {
187 cap_a == cap_b
188 }
189 (
190 TypeKind::GridStorage(_, rows_a, cols_a),
191 TypeKind::GridStorage(_, rows_b, cols_b),
192 ) => rows_a == rows_b && cols_a == cols_b,
193 _ => self.id == other.id,
195 }
196 }
197}