diff --git a/crates/fayalite/src/intern/type_map.rs b/crates/fayalite/src/intern/type_map.rs index 48433af..945116b 100644 --- a/crates/fayalite/src/intern/type_map.rs +++ b/crates/fayalite/src/intern/type_map.rs @@ -1,10 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // See Notices.txt for copyright information -use hashbrown::HashMap; use std::{ any::{Any, TypeId}, hash::{BuildHasher, Hasher}, - ptr::NonNull, sync::RwLock, }; @@ -75,59 +73,36 @@ impl BuildHasher for TypeIdBuildHasher { } } -struct Value(NonNull); - -impl Value { - unsafe fn get_transmute_lifetime<'b>(&self) -> &'b (dyn Any + Send + Sync) { - unsafe { &*self.0.as_ptr() } - } - fn new(v: Box) -> Self { - unsafe { Self(NonNull::new_unchecked(Box::into_raw(v))) } - } -} - -unsafe impl Send for Value {} -unsafe impl Sync for Value {} - -impl Drop for Value { - fn drop(&mut self) { - unsafe { std::ptr::drop_in_place(self.0.as_ptr()) } - } -} - -pub struct TypeIdMap(RwLock>); +pub(crate) struct TypeIdMap( + RwLock>, +); impl TypeIdMap { - pub const fn new() -> Self { - Self(RwLock::new(HashMap::with_hasher(TypeIdBuildHasher))) + pub(crate) const fn new() -> Self { + Self(RwLock::new(hashbrown::HashMap::with_hasher( + TypeIdBuildHasher, + ))) } #[cold] - unsafe fn insert_slow( + fn insert_slow( &self, type_id: TypeId, make: fn() -> Box, - ) -> &(dyn Any + Sync + Send) { - let value = Value::new(make()); + ) -> &'static (dyn Any + Sync + Send) { + let value = Box::leak(make()); let mut write_guard = self.0.write().unwrap(); - unsafe { - write_guard - .entry(type_id) - .or_insert(value) - .get_transmute_lifetime() - } + *write_guard.entry(type_id).or_insert(value) } - pub fn get_or_insert_default(&self) -> &T { + pub(crate) fn get_or_insert_default(&self) -> &T { let type_id = TypeId::of::(); let read_guard = self.0.read().unwrap(); - let retval = read_guard - .get(&type_id) - .map(|v| unsafe { Value::get_transmute_lifetime(v) }); + let retval = read_guard.get(&type_id).map(|v| *v); drop(read_guard); let retval = match retval { Some(retval) => retval, - None => unsafe { self.insert_slow(type_id, move || Box::new(T::default())) }, + None => self.insert_slow(type_id, move || Box::new(T::default())), }; - unsafe { &*(retval as *const dyn Any as *const T) } + retval.downcast_ref().expect("known to have correct TypeId") } }