1use core::{
4 any::Any,
5 hash::{Hash, Hasher},
6};
7
8#[doc(hidden)]
10pub use alloc::boxed::Box;
11
12pub trait DynEq: Any {
15 fn as_any(&self) -> &dyn Any;
17
18 fn dyn_eq(&self, other: &dyn DynEq) -> bool;
23}
24
25const _: Option<Box<dyn DynEq>> = None;
27
28impl<T> DynEq for T
29where
30 T: Any + Eq,
31{
32 fn as_any(&self) -> &dyn Any {
33 self
34 }
35
36 fn dyn_eq(&self, other: &dyn DynEq) -> bool {
37 if let Some(other) = other.as_any().downcast_ref::<T>() {
38 return self == other;
39 }
40 false
41 }
42}
43
44pub trait DynHash: DynEq {
47 fn as_dyn_eq(&self) -> &dyn DynEq;
49
50 fn dyn_hash(&self, state: &mut dyn Hasher);
52}
53
54const _: Option<Box<dyn DynHash>> = None;
56
57impl<T> DynHash for T
58where
59 T: DynEq + Hash,
60{
61 fn as_dyn_eq(&self) -> &dyn DynEq {
62 self
63 }
64
65 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
66 T::hash(self, &mut state);
67 self.type_id().hash(&mut state);
68 }
69}
70
71#[macro_export]
100macro_rules! define_label {
101 (
102 $(#[$label_attr:meta])*
103 $label_trait_name:ident,
104 $interner_name:ident
105 ) => {
106 $crate::define_label!(
107 $(#[$label_attr])*
108 $label_trait_name,
109 $interner_name,
110 extra_methods: {},
111 extra_methods_impl: {}
112 );
113 };
114 (
115 $(#[$label_attr:meta])*
116 $label_trait_name:ident,
117 $interner_name:ident,
118 extra_methods: { $($trait_extra_methods:tt)* },
119 extra_methods_impl: { $($interned_extra_methods_impl:tt)* }
120 ) => {
121
122 $(#[$label_attr])*
123 pub trait $label_trait_name: 'static + Send + Sync + ::core::fmt::Debug {
124
125 $($trait_extra_methods)*
126
127 #[doc = stringify!($label_trait_name)]
129 fn dyn_clone(&self) -> $crate::label::Box<dyn $label_trait_name>;
131
132 fn as_dyn_eq(&self) -> &dyn $crate::label::DynEq;
134
135 fn dyn_hash(&self, state: &mut dyn ::core::hash::Hasher);
137
138 fn intern(&self) -> $crate::intern::Interned<dyn $label_trait_name>
140 where Self: Sized {
141 $interner_name.intern(self)
142 }
143 }
144
145 #[diagnostic::do_not_recommend]
146 impl $label_trait_name for $crate::intern::Interned<dyn $label_trait_name> {
147
148 $($interned_extra_methods_impl)*
149
150 fn dyn_clone(&self) -> $crate::label::Box<dyn $label_trait_name> {
151 (**self).dyn_clone()
152 }
153
154 fn as_dyn_eq(&self) -> &dyn $crate::label::DynEq {
156 (**self).as_dyn_eq()
157 }
158
159 fn dyn_hash(&self, state: &mut dyn ::core::hash::Hasher) {
160 (**self).dyn_hash(state);
161 }
162
163 fn intern(&self) -> Self {
164 *self
165 }
166 }
167
168 impl PartialEq for dyn $label_trait_name {
169 fn eq(&self, other: &Self) -> bool {
170 self.as_dyn_eq().dyn_eq(other.as_dyn_eq())
171 }
172 }
173
174 impl Eq for dyn $label_trait_name {}
175
176 impl ::core::hash::Hash for dyn $label_trait_name {
177 fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
178 self.dyn_hash(state);
179 }
180 }
181
182 impl $crate::intern::Internable for dyn $label_trait_name {
183 fn leak(&self) -> &'static Self {
184 $crate::label::Box::leak(self.dyn_clone())
185 }
186
187 fn ref_eq(&self, other: &Self) -> bool {
188 use ::core::ptr;
189
190 self.as_dyn_eq().type_id() == other.as_dyn_eq().type_id()
192 && ptr::addr_eq(ptr::from_ref::<Self>(self), ptr::from_ref::<Self>(other))
193 }
194
195 fn ref_hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
196 use ::core::{hash::Hash, ptr};
197
198 self.as_dyn_eq().type_id().hash(state);
200
201 ptr::from_ref::<Self>(self).cast::<()>().hash(state);
204 }
205 }
206
207 static $interner_name: $crate::intern::Interner<dyn $label_trait_name> =
208 $crate::intern::Interner::new();
209 };
210}