1use crate::type_kind::TypeKind;
7
8#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
10pub struct TypeFlags(u32);
11
12impl Default for TypeFlags {
13 fn default() -> Self {
14 Self::new()
15 }
16}
17
18impl TypeFlags {
19 pub const NONE: Self = Self(0);
20 pub const IS_BLITTABLE: Self = Self(1 << 0);
22 pub const IS_SCALAR: Self = Self(1 << 1);
24 pub const IS_STORAGE: Self = Self(1 << 2);
26 pub const IS_ALLOWED_RETURN: Self = Self(1 << 3);
27
28 #[must_use]
29 pub const fn new() -> Self {
30 Self::NONE
31 }
32
33 #[must_use]
34 pub const fn contains(self, flag: Self) -> bool {
35 (self.0 & flag.0) != 0
36 }
37
38 #[must_use]
39 pub const fn union(self, other: Self) -> Self {
40 Self(self.0 | other.0)
41 }
42
43 #[allow(clippy::too_many_lines)]
45 #[must_use]
46 pub fn compute_for_type_kind(kind: &TypeKind) -> Self {
47 let mut flags = Self::NONE;
48
49 match kind {
50 TypeKind::Never => {
51 flags = flags.union(Self::IS_ALLOWED_RETURN);
52 }
53 TypeKind::Any => {
54 flags = flags
55 .union(Self::IS_BLITTABLE)
56 .union(Self::IS_STORAGE)
57 .union(Self::IS_ALLOWED_RETURN);
58 }
59 TypeKind::Codepoint => {
60 flags = flags
61 .union(Self::IS_BLITTABLE)
62 .union(Self::IS_STORAGE)
63 .union(Self::IS_ALLOWED_RETURN)
64 .union(Self::IS_SCALAR);
65 }
66 TypeKind::Byte => {
67 flags = flags
68 .union(Self::IS_BLITTABLE)
69 .union(Self::IS_STORAGE)
70 .union(Self::IS_ALLOWED_RETURN)
71 .union(Self::IS_SCALAR);
72 }
73 TypeKind::Int => {
74 flags = flags
75 .union(Self::IS_BLITTABLE)
76 .union(Self::IS_STORAGE)
77 .union(Self::IS_ALLOWED_RETURN)
78 .union(Self::IS_SCALAR);
79 }
80 TypeKind::String(..) => {
81 flags = flags
82 .union(Self::IS_BLITTABLE)
83 .union(Self::IS_ALLOWED_RETURN)
84 .union(Self::IS_SCALAR);
85 }
86 TypeKind::StringStorage(_, _, _) => {
87 flags = flags
88 .union(Self::IS_BLITTABLE)
89 .union(Self::IS_STORAGE)
90 .union(Self::IS_SCALAR);
91 }
92
93 TypeKind::Float => {
94 flags = flags
95 .union(Self::IS_BLITTABLE)
96 .union(Self::IS_STORAGE)
97 .union(Self::IS_ALLOWED_RETURN)
98 .union(Self::IS_SCALAR);
99 }
100 TypeKind::Bool => {
101 flags = flags
102 .union(Self::IS_BLITTABLE)
103 .union(Self::IS_STORAGE)
104 .union(Self::IS_ALLOWED_RETURN)
105 .union(Self::IS_SCALAR);
106 }
107 TypeKind::Unit => {
108 flags = flags
109 .union(Self::IS_BLITTABLE)
110 .union(Self::IS_STORAGE)
111 .union(Self::IS_ALLOWED_RETURN)
112 .union(Self::IS_SCALAR);
113 }
114 TypeKind::Function(_) => {}
115 TypeKind::Enum(enum_type) => {
116 if enum_type.are_all_variants_with_blittable_payload() {
117 flags = flags
118 .union(Self::IS_BLITTABLE)
119 .union(Self::IS_ALLOWED_RETURN);
120 } else {
121 panic!("enums should be blittable")
122 }
123 if enum_type.are_all_variants_with_storage_payload() {
124 flags = flags.union(Self::IS_STORAGE);
125 }
126 }
127 TypeKind::Tuple(types) => {
128 if types.iter().all(|t| t.flags.contains(Self::IS_BLITTABLE)) {
130 flags = flags
131 .union(Self::IS_BLITTABLE)
132 .union(Self::IS_ALLOWED_RETURN);
133 }
134 if types.iter().all(|t| t.flags.contains(Self::IS_STORAGE)) {
135 flags = flags.union(Self::IS_STORAGE);
136 }
137 }
138 TypeKind::Optional(inner) => {
139 if inner.flags.contains(Self::IS_BLITTABLE) {
141 flags = flags.union(Self::IS_BLITTABLE);
142 }
143 if inner.flags.contains(Self::IS_ALLOWED_RETURN) {
145 flags = flags.union(Self::IS_ALLOWED_RETURN);
146 }
147 if inner.flags.contains(Self::IS_STORAGE) {
148 flags = flags.union(Self::IS_STORAGE);
149 }
150 }
151 TypeKind::NamedStruct(named) => {
152 if named.anon_struct_type.flags.contains(Self::IS_BLITTABLE) {
153 flags = flags.union(Self::IS_BLITTABLE);
154 }
155 if named.anon_struct_type.flags.contains(Self::IS_STORAGE) {
156 flags = flags.union(Self::IS_STORAGE);
157 }
158 if named
159 .anon_struct_type
160 .flags
161 .contains(Self::IS_ALLOWED_RETURN)
162 {
163 flags = flags.union(Self::IS_ALLOWED_RETURN);
164 }
165 }
166 TypeKind::AnonymousStruct(anon) => {
167 if anon
168 .field_name_sorted_fields
169 .iter()
170 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_BLITTABLE))
171 {
172 flags = flags.union(Self::IS_BLITTABLE);
173 }
174
175 anon.field_name_sorted_fields
176 .iter()
177 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_ALLOWED_RETURN));
178 flags = flags.union(Self::IS_ALLOWED_RETURN);
179
180 if anon
181 .field_name_sorted_fields
182 .iter()
183 .all(|(_name, field)| field.field_type.flags.contains(Self::IS_STORAGE))
184 {
185 flags = flags.union(Self::IS_STORAGE);
186 }
187 }
188 TypeKind::MapStorage(key, value, _) => {
189 if key.is_blittable() && value.is_blittable() {
190 flags = flags.union(Self::IS_BLITTABLE);
191 }
192
193 if key.is_storage() && value.is_storage() {
194 flags = flags.union(Self::IS_STORAGE);
195 }
196 }
197 TypeKind::DynamicLengthMapView(_, _) => {
198 flags = flags.union(Self::IS_ALLOWED_RETURN);
199 }
200 TypeKind::FixedCapacityAndLengthArray(inner, _) => {
201 if inner.is_blittable() {
202 flags = flags.union(Self::IS_BLITTABLE);
203 }
204 if inner.is_storage() {
205 flags = flags.union(Self::IS_STORAGE);
206 }
207 }
208 TypeKind::SliceView(_) => {
209 flags = flags.union(Self::IS_ALLOWED_RETURN);
210 }
211 TypeKind::VecStorage(inner, _) => {
212 if inner.is_blittable() {
213 flags = flags.union(Self::IS_BLITTABLE);
214 }
215 if inner.is_storage() {
216 flags = flags.union(Self::IS_STORAGE);
217 }
218 }
219 TypeKind::DynamicLengthVecView(_) => {
220 flags = flags.union(Self::IS_ALLOWED_RETURN);
221 }
222
223 TypeKind::StackStorage(inner, _) => {
224 if inner.is_blittable() {
225 flags = flags.union(Self::IS_BLITTABLE);
226 }
227 if inner.is_storage() {
228 flags = flags.union(Self::IS_STORAGE);
229 }
230 }
231 TypeKind::StackView(_) => {
232 flags = flags.union(Self::IS_ALLOWED_RETURN);
233 }
234
235 TypeKind::QueueStorage(inner, _) => {
236 if inner.is_blittable() {
237 flags = flags.union(Self::IS_BLITTABLE);
238 }
239 if inner.is_storage() {
240 flags = flags.union(Self::IS_STORAGE);
241 }
242 }
243 TypeKind::QueueView(_) => {
244 flags = flags.union(Self::IS_ALLOWED_RETURN);
245 }
246 TypeKind::GridStorage(inner, _, _) => {
247 if inner.is_blittable() {
248 flags = flags.union(Self::IS_BLITTABLE);
249 }
250 if inner.is_storage() {
251 flags = flags.union(Self::IS_STORAGE);
252 }
253 }
254 TypeKind::GridView(_) => {
255 flags = flags.union(Self::IS_ALLOWED_RETURN);
256 }
257 TypeKind::SparseStorage(inner, _) => {
258 if inner.is_blittable() {
259 flags = flags.union(Self::IS_BLITTABLE);
260 }
261 if inner.is_storage() {
262 flags = flags.union(Self::IS_STORAGE);
263 }
264 }
265 TypeKind::SparseView(_) => {
266 flags = flags.union(Self::IS_ALLOWED_RETURN);
267 }
268 TypeKind::Range(_inner) => {
269 flags = flags
270 .union(Self::IS_BLITTABLE)
271 .union(Self::IS_ALLOWED_RETURN);
272 flags = flags.union(Self::IS_STORAGE);
273 }
274 }
275
276 flags
277 }
278}