rib/inferred_type/
type_internal.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Golem Source License v1.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://license.golem.cloud/LICENSE
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::inferred_type::TypeOrigin;
16use crate::{ComponentDependencyKey, InferredType, InstanceType};
17use std::hash::{Hash, Hasher};
18
19#[derive(Debug, Clone, Ord, PartialOrd)]
20pub enum TypeInternal {
21    Bool,
22    S8,
23    U8,
24    S16,
25    U16,
26    S32,
27    U32,
28    S64,
29    U64,
30    F32,
31    F64,
32    Chr,
33    Str,
34    List(InferredType),
35    Tuple(Vec<InferredType>),
36    Record(Vec<(String, InferredType)>),
37    Flags(Vec<String>),
38    Enum(Vec<String>),
39    Option(InferredType),
40    Result {
41        ok: Option<InferredType>,
42        error: Option<InferredType>,
43    },
44    Variant(Vec<(String, Option<InferredType>)>),
45    Resource {
46        name: Option<String>,
47        owner: Option<String>,
48        resource_id: u64,
49        resource_mode: u8,
50    },
51    Range {
52        from: InferredType,
53        to: Option<InferredType>,
54    },
55    Instance {
56        instance_type: Box<InstanceType>,
57    },
58    AllOf(Vec<InferredType>),
59    Unknown,
60    // Because function result can be a vector of types
61    Sequence(Vec<InferredType>),
62}
63
64impl TypeInternal {
65    pub fn is_instance(&self) -> bool {
66        matches!(self, TypeInternal::Instance { .. })
67    }
68
69    pub fn to_inferred_type(&self) -> InferredType {
70        InferredType::new(self.clone(), TypeOrigin::NoOrigin)
71    }
72
73    pub fn narrow_to_single_component(
74        &mut self,
75        component_dependency_key: &ComponentDependencyKey,
76    ) {
77        if let TypeInternal::Instance { instance_type } = self {
78            instance_type.narrow_to_single_component(component_dependency_key)
79        }
80    }
81}
82
83impl Eq for TypeInternal {}
84
85impl Hash for TypeInternal {
86    fn hash<H: Hasher>(&self, state: &mut H) {
87        match self {
88            TypeInternal::Bool => 0.hash(state),
89            TypeInternal::S8 => 1.hash(state),
90            TypeInternal::U8 => 2.hash(state),
91            TypeInternal::S16 => 3.hash(state),
92            TypeInternal::U16 => 4.hash(state),
93            TypeInternal::S32 => 5.hash(state),
94            TypeInternal::U32 => 6.hash(state),
95            TypeInternal::S64 => 7.hash(state),
96            TypeInternal::U64 => 8.hash(state),
97            TypeInternal::F32 => 9.hash(state),
98            TypeInternal::F64 => 10.hash(state),
99            TypeInternal::Chr => 11.hash(state),
100            TypeInternal::Str => 12.hash(state),
101            TypeInternal::List(inner) => {
102                13.hash(state);
103                inner.hash(state);
104            }
105            TypeInternal::Tuple(inner) => {
106                14.hash(state);
107                inner.hash(state);
108            }
109            TypeInternal::Record(fields) => {
110                15.hash(state);
111                let mut sorted_fields = fields.clone();
112                sorted_fields.sort_by(|a, b| a.0.cmp(&b.0));
113                sorted_fields.hash(state);
114            }
115            TypeInternal::Flags(flags) => {
116                16.hash(state);
117                let mut sorted_flags = flags.clone();
118                sorted_flags.sort();
119                sorted_flags.hash(state);
120            }
121            TypeInternal::Enum(variants) => {
122                17.hash(state);
123                let mut sorted_variants = variants.clone();
124                sorted_variants.sort();
125                sorted_variants.hash(state);
126            }
127            TypeInternal::Option(inner) => {
128                18.hash(state);
129                inner.hash(state);
130            }
131            TypeInternal::Result { ok, error } => {
132                19.hash(state);
133                ok.hash(state);
134                error.hash(state);
135            }
136            TypeInternal::Variant(fields) => {
137                20.hash(state);
138                let mut sorted_fields = fields.clone();
139                sorted_fields.sort_by(|a, b| a.0.cmp(&b.0));
140                sorted_fields.hash(state);
141            }
142            TypeInternal::Resource {
143                resource_id,
144                resource_mode,
145                name,
146                owner,
147            } => {
148                21.hash(state);
149                resource_id.hash(state);
150                resource_mode.hash(state);
151                if let Some(name) = name {
152                    name.hash(state);
153                } else {
154                    "name-unknown".hash(state);
155                }
156
157                if let Some(owner) = owner {
158                    owner.hash(state);
159                } else {
160                    "owner-unknown".hash(state);
161                }
162            }
163            TypeInternal::Range { from, to } => {
164                22.hash(state);
165                from.hash(state);
166                to.hash(state);
167            }
168            TypeInternal::Instance { instance_type } => {
169                23.hash(state);
170                instance_type.hash(state);
171            }
172            TypeInternal::AllOf(types) | TypeInternal::Sequence(types) => {
173                24.hash(state);
174                let mut sorted_types = types.clone();
175                sorted_types.sort();
176                sorted_types.hash(state);
177            }
178            TypeInternal::Unknown => 25.hash(state),
179        }
180    }
181}
182
183impl PartialEq for TypeInternal {
184    fn eq(&self, other: &Self) -> bool {
185        match (self, other) {
186            (TypeInternal::Bool, TypeInternal::Bool) => true,
187            (TypeInternal::S8, TypeInternal::S8) => true,
188            (TypeInternal::U8, TypeInternal::U8) => true,
189            (TypeInternal::S16, TypeInternal::S16) => true,
190            (TypeInternal::U16, TypeInternal::U16) => true,
191            (TypeInternal::S32, TypeInternal::S32) => true,
192            (TypeInternal::U32, TypeInternal::U32) => true,
193            (TypeInternal::S64, TypeInternal::S64) => true,
194            (TypeInternal::U64, TypeInternal::U64) => true,
195            (TypeInternal::F32, TypeInternal::F32) => true,
196            (TypeInternal::F64, TypeInternal::F64) => true,
197            (TypeInternal::Chr, TypeInternal::Chr) => true,
198            (TypeInternal::Str, TypeInternal::Str) => true,
199            (TypeInternal::List(t1), TypeInternal::List(t2)) => t1 == t2,
200            (TypeInternal::Tuple(ts1), TypeInternal::Tuple(ts2)) => ts1 == ts2,
201            (TypeInternal::Record(fs1), TypeInternal::Record(fs2)) => fs1 == fs2,
202            (TypeInternal::Flags(vs1), TypeInternal::Flags(vs2)) => vs1 == vs2,
203            (TypeInternal::Enum(vs1), TypeInternal::Enum(vs2)) => vs1 == vs2,
204            (TypeInternal::Option(t1), TypeInternal::Option(t2)) => t1 == t2,
205            (
206                TypeInternal::Result {
207                    ok: ok1,
208                    error: error1,
209                },
210                TypeInternal::Result {
211                    ok: ok2,
212                    error: error2,
213                },
214            ) => ok1 == ok2 && error1 == error2,
215            (TypeInternal::Variant(vs1), TypeInternal::Variant(vs2)) => vs1 == vs2,
216            (
217                TypeInternal::Resource {
218                    resource_id: id1,
219                    resource_mode: mode1,
220                    name: name1,
221                    owner: owner1,
222                },
223                TypeInternal::Resource {
224                    resource_id: id2,
225                    resource_mode: mode2,
226                    name: name2,
227                    owner: owner2,
228                },
229            ) => id1 == id2 && mode1 == mode2 && name1 == name2 && owner1 == owner2,
230            (
231                TypeInternal::Range {
232                    from: from1,
233                    to: to1,
234                },
235                TypeInternal::Range {
236                    from: from2,
237                    to: to2,
238                },
239            ) => from1 == from2 && to1 == to2,
240            (
241                TypeInternal::Instance { instance_type: t1 },
242                TypeInternal::Instance { instance_type: t2 },
243            ) => t1 == t2,
244            (TypeInternal::Unknown, TypeInternal::Unknown) => true,
245
246            (TypeInternal::AllOf(ts1), TypeInternal::AllOf(ts2)) => {
247                let mut ts1_sorted = ts1.clone();
248                let mut ts2_sorted = ts2.clone();
249                ts1_sorted.sort();
250                ts2_sorted.sort();
251                ts1_sorted == ts2_sorted
252            }
253            (TypeInternal::Sequence(ts1), TypeInternal::Sequence(ts2)) => {
254                let mut ts1_sorted = ts1.clone();
255                let mut ts2_sorted = ts2.clone();
256                ts1_sorted.sort();
257                ts2_sorted.sort();
258                ts1_sorted == ts2_sorted
259            }
260
261            _ => false,
262        }
263    }
264}