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 dyn_eq(&self, other: &dyn DynEq) -> bool;
20}
21
22const _: Option<Box<dyn DynEq>> = None;
24
25impl<T> DynEq for T
26where
27 T: Any + Eq,
28{
29 fn dyn_eq(&self, other: &dyn DynEq) -> bool {
30 if let Some(other) = (other as &dyn Any).downcast_ref::<T>() {
31 return self == other;
32 }
33 false
34 }
35}
36
37pub trait DynHash: DynEq {
40 fn dyn_hash(&self, state: &mut dyn Hasher);
42}
43
44const _: Option<Box<dyn DynHash>> = None;
46
47impl<T> DynHash for T
48where
49 T: DynEq + Hash,
50{
51 fn dyn_hash(&self, mut state: &mut dyn Hasher) {
52 T::hash(self, &mut state);
53 self.type_id().hash(&mut state);
54 }
55}
56
57#[macro_export]
86macro_rules! define_label {
87 (
88 $(#[$label_attr:meta])*
89 $label_trait_name:ident,
90 $interner_name:ident
91 ) => {
92 $crate::define_label!(
93 $(#[$label_attr])*
94 $label_trait_name,
95 $interner_name,
96 extra_methods: {},
97 extra_methods_impl: {}
98 );
99 };
100 (
101 $(#[$label_attr:meta])*
102 $label_trait_name:ident,
103 $interner_name:ident,
104 extra_methods: { $($trait_extra_methods:tt)* },
105 extra_methods_impl: { $($interned_extra_methods_impl:tt)* }
106 ) => {
107
108 $(#[$label_attr])*
109 pub trait $label_trait_name: Send + Sync + ::core::fmt::Debug + $crate::label::DynEq + $crate::label::DynHash {
110
111 $($trait_extra_methods)*
112
113 #[doc = stringify!($label_trait_name)]
115 fn dyn_clone(&self) -> $crate::label::Box<dyn $label_trait_name>;
117
118 fn intern(&self) -> $crate::intern::Interned<dyn $label_trait_name>
120 where Self: Sized {
121 $interner_name.intern(self)
122 }
123 }
124
125 #[diagnostic::do_not_recommend]
126 impl $label_trait_name for $crate::intern::Interned<dyn $label_trait_name> {
127
128 $($interned_extra_methods_impl)*
129
130 fn dyn_clone(&self) -> $crate::label::Box<dyn $label_trait_name> {
131 (**self).dyn_clone()
132 }
133
134 fn intern(&self) -> Self {
135 *self
136 }
137 }
138
139 impl PartialEq for dyn $label_trait_name {
140 fn eq(&self, other: &Self) -> bool {
141 self.dyn_eq(other)
142 }
143 }
144
145 impl Eq for dyn $label_trait_name {}
146
147 impl ::core::hash::Hash for dyn $label_trait_name {
148 fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
149 self.dyn_hash(state);
150 }
151 }
152
153 impl $crate::intern::Internable for dyn $label_trait_name {
154 fn leak(&self) -> &'static Self {
155 $crate::label::Box::leak(self.dyn_clone())
156 }
157
158 fn ref_eq(&self, other: &Self) -> bool {
159 use ::core::ptr;
160
161 self.type_id() == other.type_id()
163 && ptr::addr_eq(ptr::from_ref::<Self>(self), ptr::from_ref::<Self>(other))
164 }
165
166 fn ref_hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
167 use ::core::{hash::Hash, ptr};
168
169 self.type_id().hash(state);
171
172 ptr::from_ref::<Self>(self).cast::<()>().hash(state);
175 }
176 }
177
178 static $interner_name: $crate::intern::Interner<dyn $label_trait_name> =
179 $crate::intern::Interner::new();
180 };
181}