cubecl_ir/
type_hash.rs

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