1use super::PathId;
2use crate::ds::vec::BoxedSlice;
3use any_intern::Interned;
4use logic_eval_util::unique::{PairIter, UniqueContainer};
5use std::{
6 cell::Cell,
7 fmt::{self, Write},
8 hash::{Hash, Hasher},
9 iter, ops,
10 ptr::NonNull,
11};
12
13#[derive(Debug, Clone)]
14pub enum Type<'gcx> {
15 Scalar(TypeScalar),
16 Path(TypePath<'gcx>),
17 Tuple(TypeTuple),
18 Array(TypeArray),
19 Ref(TypeRef),
20 Mut(TypeMut),
21 Unit,
22}
23
24impl<'gcx> Hash for Type<'gcx> {
25 fn hash<H: Hasher>(&self, state: &mut H) {
26 #[repr(u8)]
27 enum TypeKind {
28 Scalar,
29 Path,
30 Tuple,
31 Array,
32 Ref,
33 Mut,
34 Unit,
35 }
36
37 match self {
38 Self::Scalar(scalar) => {
39 state.write_u8(TypeKind::Scalar as u8);
40 scalar.hash(state);
41 }
42 Self::Path(TypePath { pid, params: _ }) => {
43 state.write_u8(TypeKind::Path as u8);
45 pid.hash(state);
46 }
47 Self::Tuple(elems) => {
48 state.write_u8(TypeKind::Tuple as u8);
49 elems.hash(state);
50 }
51 Self::Array(arr) => {
52 state.write_u8(TypeKind::Array as u8);
53 arr.hash(state);
54 }
55 Self::Ref(ref_) => {
56 state.write_u8(TypeKind::Ref as u8);
57 ref_.hash(state);
58 }
59 Self::Mut(mut_) => {
60 state.write_u8(TypeKind::Mut as u8);
61 mut_.hash(state);
62 }
63 Self::Unit => state.write_u8(TypeKind::Unit as u8),
64 }
65 }
66}
67
68impl<'gcx> PartialEq for Type<'gcx> {
69 fn eq(&self, other: &Self) -> bool {
70 match self {
71 Self::Scalar(l) => matches!(other, Self::Scalar(r) if l == r),
72 Self::Path(l) => {
73 matches!(other, Self::Path(r) if l.pid == r.pid)
76 }
77 Self::Tuple(l) => matches!(other, Self::Tuple(r) if l == r),
78 Self::Array(l) => matches!(other, Self::Array(r) if l == r),
79 Self::Ref(l) => matches!(other, Self::Ref(r) if l == r),
80 Self::Mut(l) => matches!(other, Self::Mut(r) if l == r),
81 Self::Unit => matches!(other, Self::Unit),
82 }
83 }
84}
85
86impl Eq for Type<'_> {}
87
88#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
89pub enum TypeScalar {
90 Int,
91 Float,
92 I8,
93 I16,
94 I32,
95 I64,
96 I128,
97 Isize,
98 U8,
99 U16,
100 U32,
101 U64,
102 U128,
103 Usize,
104 F32,
105 F64,
106 Bool,
107}
108
109impl TypeScalar {
110 pub(crate) fn from_type_name(name: &str) -> Option<Self> {
111 match name {
112 "i8" => Some(Self::I8),
113 "i16" => Some(Self::I16),
114 "i32" => Some(Self::I32),
115 "i64" => Some(Self::I64),
116 "i128" => Some(Self::I128),
117 "isize" => Some(Self::Isize),
118 "u8" => Some(Self::U8),
119 "u16" => Some(Self::U16),
120 "u32" => Some(Self::U32),
121 "u64" => Some(Self::U64),
122 "u128" => Some(Self::U128),
123 "usize" => Some(Self::Usize),
124 "f32" => Some(Self::F32),
125 "f64" => Some(Self::F64),
126 "bool" => Some(Self::Bool),
127 _ => None,
128 }
129 }
130
131 pub(crate) fn to_type_name(self) -> &'static str {
132 match self {
133 Self::Int => "i32",
134 Self::Float => "f32",
135 Self::I8 => "i8",
136 Self::I16 => "i16",
137 Self::I32 => "i32",
138 Self::I64 => "i64",
139 Self::I128 => "i128",
140 Self::Isize => "isize",
141 Self::U8 => "u8",
142 Self::U16 => "u16",
143 Self::U32 => "u32",
144 Self::U64 => "u64",
145 Self::U128 => "u128",
146 Self::Usize => "usize",
147 Self::F32 => "f32",
148 Self::F64 => "f64",
149 Self::Bool => "bool",
150 }
151 }
152}
153
154#[derive(Debug, Clone)]
155pub struct TypePath<'gcx> {
156 pub pid: PathId,
157 pub params: BoxedSlice<Param<'gcx>>,
158}
159
160#[derive(Debug, Clone)]
161pub enum Param<'gcx> {
162 Self_,
163 Other {
164 name: Interned<'gcx, str>,
165 tid: TypeId,
166 },
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Hash)]
170pub struct TypeTuple {
171 pub elems: BoxedSlice<TypeId>,
172}
173
174#[derive(Debug, Clone, PartialEq, Eq, Hash)]
175pub struct TypeArray {
176 pub elem: TypeId,
177 pub len: ArrayLen,
178}
179
180#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
181pub enum ArrayLen {
182 Fixed(usize),
183 Dynamic,
184 Generic,
185}
186
187#[derive(Debug, Clone, PartialEq, Eq, Hash)]
188pub struct TypeRef {
189 pub elem: TypeId,
190}
191
192#[derive(Debug, Clone, PartialEq, Eq, Hash)]
193pub struct TypeMut {
194 pub elem: TypeId,
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
198pub struct TypeId(pub(crate) usize);
199
200impl TypeId {
201 pub unsafe fn new(index: usize) -> Self {
205 Self(index)
206 }
207}
208
209#[derive(PartialEq, Eq, Hash, Clone, Default)]
212pub enum OwnedType {
213 Path {
215 name: String,
216 params: BoxedSlice<OwnedParam>,
217 },
218 Tuple(BoxedSlice<OwnedType>),
220 Array { elem: Box<OwnedType>, len: ArrayLen },
222 Ref { elem: Box<OwnedType> },
224 Mut { elem: Box<OwnedType> },
226 #[default]
228 Unit,
229}
230
231impl fmt::Debug for OwnedType {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 match self {
234 Self::Path { name, .. } if name == "int" => f.write_str("int"),
235 Self::Path { name, .. } if name == "float" => f.write_str("float"),
236 Self::Path { name, .. } if name == "i8" => f.write_str("i8"),
237 Self::Path { name, .. } if name == "i16" => f.write_str("i16"),
238 Self::Path { name, .. } if name == "i32" => f.write_str("i32"),
239 Self::Path { name, .. } if name == "i64" => f.write_str("i64"),
240 Self::Path { name, .. } if name == "i128" => f.write_str("i128"),
241 Self::Path { name, .. } if name == "isize" => f.write_str("isize"),
242 Self::Path { name, .. } if name == "u8" => f.write_str("u8"),
243 Self::Path { name, .. } if name == "u16" => f.write_str("u16"),
244 Self::Path { name, .. } if name == "u32" => f.write_str("u32"),
245 Self::Path { name, .. } if name == "u64" => f.write_str("u64"),
246 Self::Path { name, .. } if name == "u128" => f.write_str("u128"),
247 Self::Path { name, .. } if name == "usize" => f.write_str("usize"),
248 Self::Path { name, .. } if name == "f32" => f.write_str("f32"),
249 Self::Path { name, .. } if name == "f64" => f.write_str("f64"),
250 Self::Path { name, .. } if name == "bool" => f.write_str("bool"),
251 Self::Path { name, params } => f
252 .debug_struct("Path")
253 .field("name", name)
254 .field("params", params)
255 .finish(),
256 Self::Tuple(elems) => f.debug_tuple("Tuple").field(elems).finish(),
257 Self::Array { elem, len } => f
258 .debug_struct("Array")
259 .field("elem", elem)
260 .field("len", len)
261 .finish(),
262 Self::Ref { elem } => f.debug_struct("Ref").field("elem", elem).finish(),
263 Self::Mut { elem } => f.debug_struct("Mut").field("elem", elem).finish(),
264 Self::Unit => f.write_str("Unit"),
265 }
266 }
267}
268
269impl fmt::Display for OwnedType {
270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271 match self {
272 Self::Path { name, .. } => f.write_str(name),
273 Self::Tuple(elems) => {
274 f.write_char('(')?;
275 for elem in elems.iter() {
276 fmt::Display::fmt(elem, f)?;
277 }
278 f.write_char(')')
279 }
280 Self::Array { elem, len } => match len {
281 ArrayLen::Fixed(n) => f.write_fmt(format_args!("[{elem}; {n}]")),
282 ArrayLen::Dynamic => f.write_fmt(format_args!("[{elem}]")),
283 ArrayLen::Generic => f.write_fmt(format_args!("[{elem}; N]")),
284 },
285 Self::Ref { elem } => f.write_fmt(format_args!("&{elem}")),
286 Self::Mut { elem } => f.write_fmt(format_args!("&mut {elem}")),
287 Self::Unit => f.write_str("()"),
288 }
289 }
290}
291
292#[derive(Debug, Clone, PartialEq, Eq, Hash)]
293pub enum OwnedParam {
294 Self_,
295 Other { name: String, ty: OwnedType },
296}
297
298pub(crate) trait CreateOwnedType {
299 fn create_owned_type(&self, tid: TypeId) -> OwnedType;
300}
301
302thread_local! {
303 pub(crate) static OWNED_TYPE_CREATOR: Cell<Option<NonNull<dyn CreateOwnedType>>> = const {
304 Cell::new(None)
305 };
306}
307
308pub struct UniqueTypes<'gcx>(UniqueContainer<Type<'gcx>>);
309
310impl<'gcx> UniqueTypes<'gcx> {
311 pub(crate) fn new() -> Self {
312 Self(UniqueContainer::new())
313 }
314
315 pub fn get(&self, tid: TypeId) -> Option<&Type<'gcx>> {
316 self.0.get(tid.0)
317 }
318
319 pub fn iter(&self) -> TypeIter<'_, 'gcx> {
320 TypeIter(self.0.iter())
321 }
322
323 pub(crate) fn insert(&mut self, ty: Type<'gcx>) -> TypeId {
324 let index = self.0.insert(ty);
325 TypeId(index)
326 }
327}
328
329impl<'gcx> ops::Deref for UniqueTypes<'gcx> {
330 type Target = UniqueContainer<Type<'gcx>>;
331
332 fn deref(&self) -> &Self::Target {
333 &self.0
334 }
335}
336
337impl ops::DerefMut for UniqueTypes<'_> {
338 fn deref_mut(&mut self) -> &mut Self::Target {
339 &mut self.0
340 }
341}
342
343impl<'gcx> ops::Index<TypeId> for UniqueTypes<'gcx> {
344 type Output = Type<'gcx>;
345
346 fn index(&self, id: TypeId) -> &Self::Output {
347 &self.0[id.0]
348 }
349}
350
351pub struct TypeIter<'a, 'gcx>(PairIter<'a, Type<'gcx>>);
352
353impl<'a, 'gcx> Iterator for TypeIter<'a, 'gcx> {
354 type Item = (TypeId, &'a Type<'gcx>);
355
356 fn next(&mut self) -> Option<Self::Item> {
357 self.0.next().map(|(index, ty)| (TypeId(index), ty))
358 }
359
360 fn size_hint(&self) -> (usize, Option<usize>) {
361 self.0.size_hint()
362 }
363}
364
365impl ExactSizeIterator for TypeIter<'_, '_> {
366 fn len(&self) -> usize {
367 self.0.len()
368 }
369}
370
371impl iter::FusedIterator for TypeIter<'_, '_> {}