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 match (&*self.kind, &*other.kind) {
16 (TypeKind::Int, TypeKind::Int) => true,
18 (TypeKind::Float, TypeKind::Float) => true,
19 (TypeKind::Bool, TypeKind::Bool) => true,
20 (TypeKind::String, TypeKind::String) => true,
21 (TypeKind::Unit, TypeKind::Unit) => true,
22
23 (TypeKind::Optional(a), TypeKind::Optional(b)) => true,
26
27 (TypeKind::VecStorage(a, cap_a), TypeKind::VecStorage(b, cap_b)) => {
28 type_cache.compatible_with(a, b)
29 }
30 (TypeKind::SparseStorage(a, cap_a), TypeKind::SparseStorage(b, cap_b)) => {
31 type_cache.compatible_with(a, b)
32 }
33 (TypeKind::QueueStorage(a, cap_a), TypeKind::QueueStorage(b, cap_b)) => {
34 type_cache.compatible_with(a, b)
35 }
36
37 (TypeKind::StackStorage(a, cap_a), TypeKind::StackStorage(b, cap_b)) => {
38 type_cache.compatible_with(a, b)
39 }
40
41 (
42 TypeKind::MapStorage(a_key, a_value, cap_a),
43 TypeKind::MapStorage(b_key, b_value, cap_b),
44 ) => {
45 type_cache.compatible_with(a_key, b_key)
46 && type_cache.compatible_with(a_value, b_value)
47 }
48
49 (
50 TypeKind::GridStorage(a, rows_a, cols_a),
51 TypeKind::GridStorage(b, rows_b, cols_b),
52 ) => rows_a >= rows_b && cols_a >= cols_b && type_cache.compatible_with(a, b),
53
54 (TypeKind::SliceView(a), TypeKind::SliceView(b)) => type_cache.compatible_with(a, b),
55 (TypeKind::SparseView(a), TypeKind::SparseView(b)) => type_cache.compatible_with(a, b),
56 (TypeKind::QueueView(a), TypeKind::QueueView(b)) => type_cache.compatible_with(a, b),
57 (TypeKind::StackView(a), TypeKind::StackView(b)) => type_cache.compatible_with(a, b),
58 (TypeKind::DynamicLengthVecView(a), TypeKind::DynamicLengthVecView(b)) => {
59 type_cache.compatible_with(a, b)
60 }
61 (
62 TypeKind::DynamicLengthMapView(a_key, a_value),
63 TypeKind::DynamicLengthMapView(b_key, b_value),
64 ) => {
65 type_cache.compatible_with(a_key, b_key)
66 && type_cache.compatible_with(a_value, b_value)
67 }
68
69 (
70 TypeKind::FixedCapacityAndLengthArray(a, size_a),
71 TypeKind::FixedCapacityAndLengthArray(b, size_b),
72 ) => {
73 size_a == size_b && type_cache.compatible_with(a, b) }
75
76 (TypeKind::Tuple(elems_a), TypeKind::Tuple(elems_b)) => {
77 elems_a.len() == elems_b.len() }
79
80 (TypeKind::AnonymousStruct(anon_a), TypeKind::AnonymousStruct(anon_b)) => {
81 anon_a.field_name_sorted_fields.len() == anon_b.field_name_sorted_fields.len()
82 && anon_a
83 .field_name_sorted_fields
84 .keys()
85 .all(|key| anon_b.field_name_sorted_fields.contains_key(key))
86 }
87
88 (TypeKind::NamedStruct(named_a), TypeKind::NamedStruct(named_b)) => {
89 named_a.assigned_name == named_b.assigned_name
90 && named_a.instantiated_type_parameters.len()
91 == named_b.instantiated_type_parameters.len()
92 }
93
94 (TypeKind::Enum(enum_a), TypeKind::Enum(enum_b)) => {
95 enum_a.assigned_name == enum_b.assigned_name
96 && enum_a.instantiated_type_parameters.len()
97 == enum_b.instantiated_type_parameters.len()
98 }
99
100 (TypeKind::Function(sig_a), TypeKind::Function(sig_b)) => {
101 sig_a.parameters.len() == sig_b.parameters.len()
102 }
103
104 _ => self.compatible_with_storage_and_view(other, type_cache),
106 }
107 }
108
109 #[must_use]
110 pub fn compatible_with_storage_and_view(
111 &self,
112 other_view: &Self,
113 type_cache: &mut TypeCache,
114 ) -> bool {
115 let left_kind = self.lowest_common_denominator_vec_like_view(type_cache);
116 let right_kind = other_view.lowest_common_denominator_vec_like_view(type_cache);
117 if left_kind.is_some() && right_kind.is_some() {
118 let left = left_kind.unwrap();
119 let right = right_kind.unwrap();
120 match (left, right) {
121 (TypeKind::SliceView(a), TypeKind::SliceView(b)) => {
122 type_cache.compatible_with(&a, &b)
123 }
124 (TypeKind::DynamicLengthVecView(a), TypeKind::DynamicLengthVecView(b)) => {
125 type_cache.compatible_with(&a, &b)
126 }
127 _ => false,
128 }
129 } else {
130 match (&*self.kind, &*other_view.kind) {
131 (
132 TypeKind::MapStorage(key_a, value_a, _),
133 TypeKind::DynamicLengthMapView(key_b, value_b),
134 )
135 | (
136 TypeKind::DynamicLengthMapView(key_a, value_a),
137 TypeKind::MapStorage(key_b, value_b, _),
138 ) => {
139 type_cache.compatible_with(key_a, key_b)
140 && type_cache.compatible_with(value_a, value_b)
141 }
142 _ => false,
143 }
144 }
145 }
146
147 #[must_use]
149 pub fn lowest_common_denominator_vec_like_view(
150 &self,
151 type_cache: &mut TypeCache,
152 ) -> Option<TypeKind> {
153 match &*self.kind {
154 TypeKind::FixedCapacityAndLengthArray(inner, _size)
155 | TypeKind::QueueStorage(inner, _size)
156 | TypeKind::StackStorage(inner, _size)
157 | TypeKind::SparseStorage(inner, _size)
158 | TypeKind::VecStorage(inner, _size) => Some(TypeKind::SliceView(inner.clone())),
159
160 TypeKind::SliceView(inner)
161 | TypeKind::QueueView(inner)
162 | TypeKind::StackView(inner)
163 | TypeKind::SparseView(inner)
164 | TypeKind::DynamicLengthVecView(inner) => Some(TypeKind::SliceView(inner.clone())),
165
166 TypeKind::StringStorage(byte_type, size) => {
167 Some(TypeKind::DynamicLengthVecView(byte_type.clone()))
168 }
169
170 TypeKind::String => Some(TypeKind::DynamicLengthVecView(type_cache.byte())),
171
172 _ => None,
173 }
174 }
175
176 #[must_use]
177 pub fn strict_compatible_with_capacity(&self, other: &Self) -> bool {
178 match (&*self.kind, &*other.kind) {
179 (TypeKind::VecStorage(_, cap_a), TypeKind::VecStorage(_, cap_b)) => cap_a == cap_b,
180 (TypeKind::SparseStorage(_, cap_a), TypeKind::SparseStorage(_, cap_b)) => {
181 cap_a == cap_b
182 }
183 (TypeKind::QueueStorage(_, cap_a), TypeKind::QueueStorage(_, cap_b)) => cap_a == cap_b,
184 (TypeKind::StackStorage(_, cap_a), TypeKind::StackStorage(_, cap_b)) => cap_a == cap_b,
185 (TypeKind::MapStorage(_, _, cap_a), TypeKind::MapStorage(_, _, cap_b)) => {
186 cap_a == cap_b
187 }
188 (
189 TypeKind::GridStorage(_, rows_a, cols_a),
190 TypeKind::GridStorage(_, rows_b, cols_b),
191 ) => rows_a == rows_b && cols_a == cols_b,
192 _ => self.id == other.id,
194 }
195 }
196}