1use std::{
4 any::Any,
5 hash::{Hash, Hasher},
6};
7
8pub trait DynEq: Any {
11 fn as_any(&self) -> &dyn Any;
13
14 fn dyn_eq(&self, other: &dyn DynEq) -> bool;
19}
20
21impl<T> DynEq for T
22where
23 T: Any + Eq,
24{
25 fn as_any(&self) -> &dyn Any {
26 self
27 }
28
29 fn dyn_eq(&self, other: &dyn DynEq) -> bool {
30 if let Some(other) = other.as_any().downcast_ref::<T>() {
31 return self == other;
32 }
33 false
34 }
35}
36
37pub trait DynHash: DynEq {
40 fn as_dyn_eq(&self) -> &dyn DynEq;
42
43 fn dyn_hash(&self, state: &mut dyn Hasher);
45}
46
47impl<T> DynHash for T
48where
49 T: DynEq + Hash,
50{
51 fn as_dyn_eq(&self) -> &dyn DynEq {
52 self
53 }
54
55 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
56 T::hash(self, &mut state);
57 self.type_id().hash(&mut state);
58 }
59}
60
61#[macro_export]
90macro_rules! define_label {
91 (
92 $(#[$label_attr:meta])*
93 $label_trait_name:ident,
94 $interner_name:ident
95 ) => {
96 $crate::define_label!(
97 $(#[$label_attr])*
98 $label_trait_name,
99 $interner_name,
100 extra_methods: {},
101 extra_methods_impl: {}
102 );
103 };
104 (
105 $(#[$label_attr:meta])*
106 $label_trait_name:ident,
107 $interner_name:ident,
108 extra_methods: { $($trait_extra_methods:tt)* },
109 extra_methods_impl: { $($interned_extra_methods_impl:tt)* }
110 ) => {
111
112 $(#[$label_attr])*
113 pub trait $label_trait_name: 'static + Send + Sync + ::std::fmt::Debug {
114
115 $($trait_extra_methods)*
116
117 #[doc = stringify!($label_trait_name)]
119 fn dyn_clone(&self) -> ::std::boxed::Box<dyn $label_trait_name>;
121
122 fn as_dyn_eq(&self) -> &dyn $crate::label::DynEq;
124
125 fn dyn_hash(&self, state: &mut dyn ::std::hash::Hasher);
127
128 fn intern(&self) -> $crate::intern::Interned<dyn $label_trait_name>
130 where Self: Sized {
131 $interner_name.intern(self)
132 }
133 }
134
135 impl $label_trait_name for $crate::intern::Interned<dyn $label_trait_name> {
136
137 $($interned_extra_methods_impl)*
138
139 fn dyn_clone(&self) -> ::std::boxed::Box<dyn $label_trait_name> {
140 (**self).dyn_clone()
141 }
142
143 fn as_dyn_eq(&self) -> &dyn $crate::label::DynEq {
145 (**self).as_dyn_eq()
146 }
147
148 fn dyn_hash(&self, state: &mut dyn ::std::hash::Hasher) {
149 (**self).dyn_hash(state);
150 }
151
152 fn intern(&self) -> Self {
153 *self
154 }
155 }
156
157 impl PartialEq for dyn $label_trait_name {
158 fn eq(&self, other: &Self) -> bool {
159 self.as_dyn_eq().dyn_eq(other.as_dyn_eq())
160 }
161 }
162
163 impl Eq for dyn $label_trait_name {}
164
165 impl ::std::hash::Hash for dyn $label_trait_name {
166 fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
167 self.dyn_hash(state);
168 }
169 }
170
171 impl $crate::intern::Internable for dyn $label_trait_name {
172 fn leak(&self) -> &'static Self {
173 Box::leak(self.dyn_clone())
174 }
175
176 fn ref_eq(&self, other: &Self) -> bool {
177 use ::std::ptr;
178
179 self.as_dyn_eq().type_id() == other.as_dyn_eq().type_id()
181 && ptr::addr_eq(ptr::from_ref::<Self>(self), ptr::from_ref::<Self>(other))
182 }
183
184 fn ref_hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
185 use ::std::{hash::Hash, ptr};
186
187 self.as_dyn_eq().type_id().hash(state);
189
190 ptr::from_ref::<Self>(self).cast::<()>().hash(state);
193 }
194 }
195
196 static $interner_name: $crate::intern::Interner<dyn $label_trait_name> =
197 $crate::intern::Interner::new();
198 };
199}