5
5
use std:: {
6
6
collections:: HashMap ,
7
7
fmt:: { self , Debug } ,
8
- hash:: { BuildHasherDefault , Hash } ,
8
+ hash:: { BuildHasherDefault , Hash , Hasher } ,
9
9
ops:: Deref ,
10
10
sync:: Arc ,
11
11
} ;
@@ -20,7 +20,6 @@ type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>;
20
20
type Guard < T > =
21
21
RwLockWriteGuard < ' static , HashMap < Arc < T > , SharedValue < ( ) > , BuildHasherDefault < FxHasher > > > ;
22
22
23
- #[ derive( Hash ) ]
24
23
pub struct Interned < T : Internable + ?Sized > {
25
24
arc : Arc < T > ,
26
25
}
@@ -137,6 +136,13 @@ impl PartialEq for Interned<str> {
137
136
138
137
impl Eq for Interned < str > { }
139
138
139
+ impl < T : Internable + ?Sized > Hash for Interned < T > {
140
+ fn hash < H : Hasher > ( & self , state : & mut H ) {
141
+ // NOTE: Cast disposes vtable pointer / slice/str length.
142
+ state. write_usize ( Arc :: as_ptr ( & self . arc ) as * const ( ) as usize )
143
+ }
144
+ }
145
+
140
146
impl < T : Internable + ?Sized > AsRef < T > for Interned < T > {
141
147
#[ inline]
142
148
fn as_ref ( & self ) -> & T {
@@ -185,7 +191,10 @@ pub trait Internable: Hash + Eq + 'static {
185
191
fn storage ( ) -> & ' static InternStorage < Self > ;
186
192
}
187
193
188
- macro_rules! impl_internable {
194
+ /// Implements `Internable` for a given list of types, making them usable with `Interned`.
195
+ #[ macro_export]
196
+ #[ doc( hidden) ]
197
+ macro_rules! _impl_internable {
189
198
( $( $t: path) ,+ $( , ) ? ) => { $(
190
199
impl Internable for $t {
191
200
fn storage( ) -> & ' static InternStorage <Self > {
@@ -196,10 +205,12 @@ macro_rules! impl_internable {
196
205
) + } ;
197
206
}
198
207
208
+ pub use crate :: _impl_internable as impl_internable;
209
+
199
210
impl_internable ! (
200
211
crate :: type_ref:: TypeRef ,
201
212
crate :: type_ref:: TraitRef ,
202
213
crate :: path:: ModPath ,
203
214
GenericParams ,
204
- str
215
+ str ,
205
216
) ;
0 commit comments