diff options
Diffstat (limited to 'crates/hir_def/src/intern.rs')
-rw-r--r-- | crates/hir_def/src/intern.rs | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs index 2467e9299..abc304ef0 100644 --- a/crates/hir_def/src/intern.rs +++ b/crates/hir_def/src/intern.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | use std::{ | 5 | use std::{ |
6 | collections::HashMap, | 6 | collections::HashMap, |
7 | fmt::{self, Debug}, | 7 | fmt::{self, Debug}, |
8 | hash::{BuildHasherDefault, Hash}, | 8 | hash::{BuildHasherDefault, Hash, Hasher}, |
9 | ops::Deref, | 9 | ops::Deref, |
10 | sync::Arc, | 10 | sync::Arc, |
11 | }; | 11 | }; |
@@ -20,7 +20,6 @@ type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>; | |||
20 | type Guard<T> = | 20 | type Guard<T> = |
21 | RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>; | 21 | RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>; |
22 | 22 | ||
23 | #[derive(Hash)] | ||
24 | pub struct Interned<T: Internable + ?Sized> { | 23 | pub struct Interned<T: Internable + ?Sized> { |
25 | arc: Arc<T>, | 24 | arc: Arc<T>, |
26 | } | 25 | } |
@@ -137,6 +136,13 @@ impl PartialEq for Interned<str> { | |||
137 | 136 | ||
138 | impl Eq for Interned<str> {} | 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 | impl<T: Internable + ?Sized> AsRef<T> for Interned<T> { | 146 | impl<T: Internable + ?Sized> AsRef<T> for Interned<T> { |
141 | #[inline] | 147 | #[inline] |
142 | fn as_ref(&self) -> &T { | 148 | fn as_ref(&self) -> &T { |
@@ -185,7 +191,10 @@ pub trait Internable: Hash + Eq + 'static { | |||
185 | fn storage() -> &'static InternStorage<Self>; | 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 | ( $($t:path),+ $(,)? ) => { $( | 198 | ( $($t:path),+ $(,)? ) => { $( |
190 | impl Internable for $t { | 199 | impl Internable for $t { |
191 | fn storage() -> &'static InternStorage<Self> { | 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 | impl_internable!( | 210 | impl_internable!( |
200 | crate::type_ref::TypeRef, | 211 | crate::type_ref::TypeRef, |
201 | crate::type_ref::TraitRef, | 212 | crate::type_ref::TraitRef, |
202 | crate::path::ModPath, | 213 | crate::path::ModPath, |
203 | GenericParams, | 214 | GenericParams, |
204 | str | 215 | str, |
205 | ); | 216 | ); |