Skip to main content

cubecl_ir/
type_hash.rs

1use crate::EnumSetType;
2use alloc::borrow::ToOwned;
3use core::hash::Hasher;
4use cubecl_common::hash::{StableHash, StableHasher};
5
6/// A hash of a type's structure
7pub trait TypeHash {
8    /// Generate a stable hash of the type structure.
9    ///
10    /// This recursively hashes the names and types of each variant and field, and uses an unseeded
11    /// hasher to ensure the hash is stable across compilations and executions. The hash should only
12    /// change if a field/variant is renamed, added, or its type is changed.
13    #[allow(unused)]
14    fn type_hash() -> StableHash {
15        let mut hasher = StableHasher::new();
16        Self::write_hash(&mut hasher);
17        hasher.finalize()
18    }
19
20    /// Write the structure of the type to the hasher
21    fn write_hash(hasher: &mut impl Hasher);
22}
23
24macro_rules! impl_type_hash {
25    ($( $($ty: ident)::* $(<$($l: lifetime,)* $($T: ident $(: $(? $Sized: ident)? $($(+)? $B: ident)*)?),+>)?,)*) => {
26        $(
27            impl $(<$($l,)* $($T: $crate::TypeHash $($(+ ?$Sized)? $(+ $B)*)? ),*>)? TypeHash for $($ty)::* $(<$($l,)* $($T),+>)? {
28                fn write_hash(hasher: &mut impl core::hash::Hasher) {
29                    hasher.write(stringify!($($ty)::*).as_bytes());
30                    $($(
31                        $T::write_hash(hasher);
32                    )+)?
33                }
34            }
35        )*
36    };
37}
38
39impl_type_hash!(
40    bool,
41    u8,
42    i8,
43    u16,
44    i16,
45    u32,
46    i32,
47    u64,
48    i64,
49    u128,
50    i128,
51    usize,
52    isize,
53    f32,
54    f64,
55    str,
56    core::any::TypeId,
57    alloc::borrow::Cow<'a, T: ?Sized + ToOwned>,
58    alloc::boxed::Box<T: ?Sized>,
59    core::cell::Cell<T: ?Sized>,
60    core::cell::Ref<'a, T: ?Sized>,
61    core::cell::RefCell<T: ?Sized>,
62    core::cell::RefMut<'a, T>,
63    core::cell::UnsafeCell<T>,
64    core::cmp::Ordering,
65    core::cmp::Reverse<T>,
66    alloc::collections::BinaryHeap<T>,
67    alloc::collections::BTreeMap<K, V>,
68    alloc::collections::BTreeSet<T>,
69    alloc::collections::LinkedList<T>,
70    alloc::collections::VecDeque<T>,
71    core::hash::BuildHasherDefault<T>,
72    core::marker::PhantomData<T: ?Sized>,
73    core::mem::ManuallyDrop<T: ?Sized>,
74    core::mem::MaybeUninit<T>,
75    core::net::IpAddr,
76    core::net::Ipv4Addr,
77    core::net::Ipv6Addr,
78    core::net::SocketAddr,
79    core::net::SocketAddrV4,
80    core::net::SocketAddrV6,
81    core::num::FpCategory,
82    core::num::NonZeroI128,
83    core::num::NonZeroI16,
84    core::num::NonZeroI32,
85    core::num::NonZeroI64,
86    core::num::NonZeroI8,
87    core::num::NonZeroIsize,
88    core::num::NonZeroU128,
89    core::num::NonZeroU16,
90    core::num::NonZeroU32,
91    core::num::NonZeroU64,
92    core::num::NonZeroU8,
93    core::num::NonZeroUsize,
94    core::num::Wrapping<T>,
95    core::ops::Bound<T>,
96    core::ops::Range<T>,
97    core::ops::RangeFrom<T>,
98    core::ops::RangeInclusive<T>,
99    core::ops::RangeFull,
100    core::ops::RangeTo<T>,
101    core::ops::RangeToInclusive<T>,
102    core::option::Option<T>,
103    core::pin::Pin<T>,
104    core::primitive::char,
105    core::ptr::NonNull<T: ?Sized>,
106    alloc::rc::Rc<T: ?Sized>,
107    alloc::rc::Weak<T: ?Sized>,
108    core::result::Result<T, E>,
109    alloc::string::String,
110    core::time::Duration,
111    alloc::vec::Vec<T>,
112    hashbrown::HashMap<K, V>,
113    hashbrown::HashSet<T>,
114    portable_atomic::AtomicBool,
115    portable_atomic::AtomicI16,
116    portable_atomic::AtomicI32,
117    portable_atomic::AtomicI64,
118    portable_atomic::AtomicI8,
119    portable_atomic::AtomicIsize,
120    portable_atomic::AtomicPtr<T>,
121    portable_atomic::AtomicU16,
122    portable_atomic::AtomicU32,
123    portable_atomic::AtomicU64,
124    portable_atomic::AtomicU8,
125    portable_atomic::AtomicUsize,
126    crate::EnumSet<T: EnumSetType>,
127    internment::Intern<T: ?Sized>,
128    bumpalo::Bump,
129    pliron::value::Value,
130);
131
132macro_rules! impl_type_hash_tuple {
133    ($($T: ident),*) => {
134        impl <$($T: $crate::TypeHash),*> TypeHash for ($($T,)*) {
135            fn write_hash(hasher: &mut impl core::hash::Hasher) {
136                hasher.write(b"()");
137                $(
138                    $T::write_hash(hasher);
139                )*
140            }
141        }
142    };
143}
144
145variadics_please::all_tuples!(impl_type_hash_tuple, 0, 16, T);
146
147impl<T: TypeHash, const N: usize> TypeHash for [T; N] {
148    fn write_hash(hasher: &mut impl core::hash::Hasher) {
149        hasher.write(b"[;]");
150        hasher.write_usize(N);
151        T::write_hash(hasher);
152    }
153}
154
155impl<T: TypeHash + ?Sized> TypeHash for *const T {
156    fn write_hash(hasher: &mut impl Hasher) {
157        hasher.write(b"*const");
158        T::write_hash(hasher);
159    }
160}
161
162impl<T: TypeHash + ?Sized> TypeHash for *mut T {
163    fn write_hash(hasher: &mut impl Hasher) {
164        hasher.write(b"*mut");
165        T::write_hash(hasher);
166    }
167}
168
169impl<T: TypeHash> TypeHash for [T] {
170    fn write_hash(hasher: &mut impl Hasher) {
171        hasher.write(b"[]");
172        T::write_hash(hasher);
173    }
174}
175
176impl<T: TypeHash + ?Sized> TypeHash for &T {
177    fn write_hash(hasher: &mut impl Hasher) {
178        hasher.write(b"&");
179        T::write_hash(hasher);
180    }
181}
182
183impl<T: TypeHash + ?Sized> TypeHash for &mut T {
184    fn write_hash(hasher: &mut impl Hasher) {
185        hasher.write(b"&mut");
186        T::write_hash(hasher);
187    }
188}
189
190impl<T: TypeHash + ?Sized, U: TypeHash + ?Sized> TypeHash for fn(T) -> U {
191    fn write_hash(hasher: &mut impl Hasher) {
192        hasher.write(b"fn(");
193        T::write_hash(hasher);
194        hasher.write(b") -> ");
195        U::write_hash(hasher);
196    }
197}