diff options
| author | Joshua Nelson <jnelson@cloudflare.com> | 2022-06-26 21:06:24 -0500 |
|---|---|---|
| committer | Joshua Nelson <jnelson@cloudflare.com> | 2022-07-02 19:29:39 -0500 |
| commit | 0566ade0b13fa5e4e09ea6d72fe7cb92a1cb13e3 (patch) | |
| tree | 9d2bee8e773d8fe0eac2ba6e07eb83eb7f1780c7 | |
| parent | ee8e0bc5824be2a05f086649815b2e10473663ea (diff) | |
| download | rust-0566ade0b13fa5e4e09ea6d72fe7cb92a1cb13e3.tar.gz rust-0566ade0b13fa5e4e09ea6d72fe7cb92a1cb13e3.zip | |
Use generics for interned types rather than copy-pasting impls
This makes it much simpler to add new interned types, rather than having to add 4+ impl blocks for each type.
| -rw-r--r-- | src/bootstrap/cache.rs | 112 |
1 files changed, 43 insertions, 69 deletions
diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 97f0bfdc484..72de0a090af 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -4,13 +4,12 @@ use std::cell::RefCell; use std::cmp::{Ord, Ordering, PartialOrd}; use std::collections::HashMap; use std::convert::AsRef; -use std::ffi::OsStr; use std::fmt; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; use std::ops::Deref; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::Mutex; // FIXME: replace with std::lazy after it gets stabilized and reaches beta @@ -20,15 +19,9 @@ use crate::builder::Step; pub struct Interned<T>(usize, PhantomData<*const T>); -impl Default for Interned<String> { +impl<T: Internable + Default> Default for Interned<T> { fn default() -> Self { - INTERNER.intern_string(String::default()) - } -} - -impl Default for Interned<PathBuf> { - fn default() -> Self { - INTERNER.intern_path(PathBuf::default()) + T::default().intern() } } @@ -77,87 +70,48 @@ impl fmt::Display for Interned<String> { } } -impl fmt::Debug for Interned<String> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s: &str = &*self; - f.write_fmt(format_args!("{:?}", s)) - } -} -impl fmt::Debug for Interned<PathBuf> { +impl<T, U: ?Sized + fmt::Debug> fmt::Debug for Interned<T> +where + Self: Deref<Target = U>, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s: &Path = &*self; + let s: &U = &*self; f.write_fmt(format_args!("{:?}", s)) } } -impl Hash for Interned<String> { +impl<T: Internable + Hash> Hash for Interned<T> { fn hash<H: Hasher>(&self, state: &mut H) { - let l = INTERNER.strs.lock().unwrap(); + let l = T::intern_cache().lock().unwrap(); l.get(*self).hash(state) } } -impl Hash for Interned<PathBuf> { - fn hash<H: Hasher>(&self, state: &mut H) { - let l = INTERNER.paths.lock().unwrap(); - l.get(*self).hash(state) - } -} - -impl Deref for Interned<String> { - type Target = str; - fn deref(&self) -> &'static str { - let l = INTERNER.strs.lock().unwrap(); - unsafe { mem::transmute::<&str, &'static str>(l.get(*self)) } - } -} - -impl Deref for Interned<PathBuf> { - type Target = Path; - fn deref(&self) -> &'static Path { - let l = INTERNER.paths.lock().unwrap(); - unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) } - } -} - -impl AsRef<Path> for Interned<PathBuf> { - fn as_ref(&self) -> &'static Path { - let l = INTERNER.paths.lock().unwrap(); - unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self)) } - } -} - -impl AsRef<Path> for Interned<String> { - fn as_ref(&self) -> &'static Path { - let l = INTERNER.strs.lock().unwrap(); - unsafe { mem::transmute::<&Path, &'static Path>(l.get(*self).as_ref()) } +impl<T: Internable + Deref> Deref for Interned<T> { + type Target = T::Target; + fn deref(&self) -> &'static Self::Target { + let l = T::intern_cache().lock().unwrap(); + unsafe { mem::transmute::<&Self::Target, &'static Self::Target>(l.get(*self)) } } } -impl AsRef<OsStr> for Interned<PathBuf> { - fn as_ref(&self) -> &'static OsStr { - let l = INTERNER.paths.lock().unwrap(); - unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) } +impl<T: Internable + AsRef<U>, U: ?Sized> AsRef<U> for Interned<T> { + fn as_ref(&self) -> &'static U { + let l = T::intern_cache().lock().unwrap(); + unsafe { mem::transmute::<&U, &'static U>(l.get(*self).as_ref()) } } } -impl AsRef<OsStr> for Interned<String> { - fn as_ref(&self) -> &'static OsStr { - let l = INTERNER.strs.lock().unwrap(); - unsafe { mem::transmute::<&OsStr, &'static OsStr>(l.get(*self).as_ref()) } - } -} - -impl PartialOrd<Interned<String>> for Interned<String> { +impl<T: Internable + PartialOrd> PartialOrd for Interned<T> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - let l = INTERNER.strs.lock().unwrap(); + let l = T::intern_cache().lock().unwrap(); l.get(*self).partial_cmp(l.get(*other)) } } -impl Ord for Interned<String> { +impl<T: Internable + Ord> Ord for Interned<T> { fn cmp(&self, other: &Self) -> Ordering { - let l = INTERNER.strs.lock().unwrap(); + let l = T::intern_cache().lock().unwrap(); l.get(*self).cmp(l.get(*other)) } } @@ -210,6 +164,26 @@ pub struct Interner { paths: Mutex<TyIntern<PathBuf>>, } +trait Internable: Clone + Eq + Hash + 'static { + fn intern_cache() -> &'static Mutex<TyIntern<Self>>; + + fn intern(self) -> Interned<Self> { + Self::intern_cache().lock().unwrap().intern(self) + } +} + +impl Internable for String { + fn intern_cache() -> &'static Mutex<TyIntern<Self>> { + &INTERNER.strs + } +} + +impl Internable for PathBuf { + fn intern_cache() -> &'static Mutex<TyIntern<Self>> { + &INTERNER.paths + } +} + impl Interner { pub fn intern_str(&self, s: &str) -> Interned<String> { self.strs.lock().unwrap().intern_borrow(s) |
