1use crate::EnumSetType;
2use alloc::borrow::ToOwned;
3use core::hash::Hasher;
4use cubecl_common::hash::{StableHash, StableHasher};
5
6pub trait TypeHash {
8 #[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 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}