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