diff --git a/.forgejo/workflows/test.yml b/.forgejo/workflows/test.yml index 7a69a7e..001168f 100644 --- a/.forgejo/workflows/test.yml +++ b/.forgejo/workflows/test.yml @@ -16,7 +16,6 @@ jobs: - uses: https://git.libre-chip.org/mirrors/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/master' }} - - run: rustup override set 1.93.0 - run: cargo test - run: cargo build --tests --features=unstable-doc - run: cargo test --doc --features=unstable-doc diff --git a/Cargo.lock b/Cargo.lock index c7e2204..be5f3bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -319,7 +319,6 @@ dependencies = [ "jobslot", "num-bigint", "num-traits", - "once_cell", "ordered-float", "petgraph", "serde", @@ -522,9 +521,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "ordered-float" diff --git a/Cargo.toml b/Cargo.toml index 504d90f..2380ea7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ edition = "2024" repository = "https://git.libre-chip.org/libre-chip/fayalite" keywords = ["hdl", "hardware", "semiconductors", "firrtl", "fpga"] categories = ["simulation", "development-tools", "compilers"] -rust-version = "1.93.0" +rust-version = "1.89.0" [workspace.dependencies] fayalite-proc-macros = { version = "=0.3.0", path = "crates/fayalite-proc-macros" } @@ -30,7 +30,6 @@ indexmap = { version = "2.5.0", features = ["serde"] } jobslot = "0.2.23" num-bigint = "0.4.6" num-traits = "0.2.16" -once_cell = "1.21.3" ordered-float = { version = "5.1.0", features = ["serde"] } petgraph = "0.8.1" prettyplease = "0.2.20" diff --git a/crates/fayalite/Cargo.toml b/crates/fayalite/Cargo.toml index 61ee5c7..fdf1c87 100644 --- a/crates/fayalite/Cargo.toml +++ b/crates/fayalite/Cargo.toml @@ -26,7 +26,6 @@ hashbrown.workspace = true jobslot.workspace = true num-bigint.workspace = true num-traits.workspace = true -once_cell.workspace = true ordered-float.workspace = true petgraph.workspace = true serde_json.workspace = true diff --git a/crates/fayalite/src/array.rs b/crates/fayalite/src/array.rs index 6ca6809..4e2b223 100644 --- a/crates/fayalite/src/array.rs +++ b/crates/fayalite/src/array.rs @@ -109,42 +109,14 @@ impl Default for ArrayType { } } -struct MakeType(Interned); - -impl From> for Interned { - fn from(value: MakeType) -> Self { - value.0 - } -} - -impl Default for MakeType { - fn default() -> Self { - Self(T::TYPE.intern_sized()) - } -} - -struct MakeMaskType(Interned); - -impl From> for Interned { - fn from(value: MakeMaskType) -> Self { - value.0 - } -} - -impl Default for MakeMaskType { - fn default() -> Self { - Self(T::MASK_TYPE.intern_sized()) - } -} - impl StaticType for ArrayType { const TYPE: Self = Self { - element: LazyInterned::new_const::>(), + element: LazyInterned::new_lazy(&|| T::TYPE.intern_sized()), len: Len::SIZE, type_properties: Self::TYPE_PROPERTIES, }; const MASK_TYPE: Self::MaskType = ArrayType:: { - element: LazyInterned::new_const::>(), + element: LazyInterned::new_lazy(&|| T::MASK_TYPE.intern_sized()), len: Len::SIZE, type_properties: Self::MASK_TYPE_PROPERTIES, }; diff --git a/crates/fayalite/src/int.rs b/crates/fayalite/src/int.rs index c461306..2d1f6d2 100644 --- a/crates/fayalite/src/int.rs +++ b/crates/fayalite/src/int.rs @@ -10,7 +10,7 @@ use crate::{ value_category::ValueCategoryValue, }, hdl, - intern::{Intern, Interned, Memoize, OnceInterned}, + intern::{Intern, Interned, Memoize}, sim::value::{SimValue, ToSimValueWithType}, source_location::SourceLocation, ty::{ @@ -65,21 +65,14 @@ pub type DynSize = ConstUsize; trait KnownSizeBaseSealed {} -impl KnownSizeBaseSealed for ConstUsize {} +impl KnownSizeBaseSealed for [(); N] {} #[expect(private_bounds)] -pub trait KnownSizeBase: KnownSizeBaseSealed + GetInternedIntCaches {} +pub trait KnownSizeBase: KnownSizeBaseSealed {} macro_rules! impl_known_size_base { ($($size:literal),* $(,)?) => { - $(impl KnownSizeBase for ConstUsize<$size> {})* - $(impl GetInternedIntCaches for ConstUsize<$size> { - #[inline(always)] - fn get_interned_int_caches() -> &'static InternedIntCaches { - static CACHES: InternedIntCaches> = InternedIntCaches::new(); - &CACHES - } - })* + $(impl KnownSizeBase for [(); $size] {})* }; } @@ -120,34 +113,12 @@ impl_known_size_base! { 0x200, } -trait GetInternedIntCaches { - fn get_interned_int_caches() -> &'static InternedIntCaches - where - Self: KnownSize; -} - -struct InternedIntCaches { - uint: OnceInterned>, - sint: OnceInterned>, -} - -impl InternedIntCaches { - const fn new() -> Self { - Self { - uint: OnceInterned::new(), - sint: OnceInterned::new(), - } - } -} - -#[expect(private_bounds)] pub trait KnownSize: GenericConstUsize + sealed::SizeTypeSealed + sealed::SizeSealed + Default + FillInDefaultedGenerics - + GetInternedIntCaches { const SIZE: Self; type ArrayMatch: AsRef<[Expr]> @@ -177,7 +148,7 @@ pub trait KnownSize: impl KnownSize for ConstUsize where - ConstUsize: KnownSizeBase, + [(); N]: KnownSizeBase, { const SIZE: Self = Self; type ArrayMatch = [Expr; N]; @@ -250,10 +221,6 @@ pub trait Size: fn from_usize(v: usize) -> Self::SizeType { Self::try_from_usize(v).expect("wrong size") } - #[doc(hidden)] - fn interned_uint(size_type: Self::SizeType) -> Interned>; - #[doc(hidden)] - fn interned_sint(size_type: Self::SizeType) -> Interned>; } impl sealed::SizeTypeSealed for usize {} @@ -262,8 +229,6 @@ impl SizeType for usize { type Size = DynSize; } -const MAX_CACHED_INT_WIDTH: usize = 1 << 10; - impl Size for DynSize { type ArrayMatch = Box<[Expr]>; type ArraySimValue = Box<[SimValue]>; @@ -277,36 +242,6 @@ impl Size for DynSize { fn try_from_usize(v: usize) -> Option { Some(v) } - - #[doc(hidden)] - fn interned_uint(size_type: Self::SizeType) -> Interned> { - static CACHED: [OnceInterned; MAX_CACHED_INT_WIDTH] = - [const { OnceInterned::new() }; _]; - #[cold] - fn intern_cold(width: usize) -> Interned { - Intern::intern_sized(UInt::new(width)) - } - if let Some(cached) = CACHED.get(size_type) { - cached.get_or_init(|| intern_cold(size_type)) - } else { - intern_cold(size_type) - } - } - - #[doc(hidden)] - fn interned_sint(size_type: Self::SizeType) -> Interned> { - static CACHED: [OnceInterned; MAX_CACHED_INT_WIDTH] = - [const { OnceInterned::new() }; _]; - #[cold] - fn intern_cold(width: usize) -> Interned { - Intern::intern_sized(SInt::new(width)) - } - if let Some(cached) = CACHED.get(size_type) { - cached.get_or_init(|| intern_cold(size_type)) - } else { - intern_cold(size_type) - } - } } impl sealed::SizeSealed for ConstUsize {} @@ -332,20 +267,6 @@ impl Size for T { fn try_from_usize(v: usize) -> Option { if v == T::VALUE { Some(T::SIZE) } else { None } } - - #[doc(hidden)] - fn interned_uint(_size_type: Self::SizeType) -> Interned> { - T::get_interned_int_caches() - .uint - .get_or_init(|| UIntType::new_static().intern_sized()) - } - - #[doc(hidden)] - fn interned_sint(_size_type: Self::SizeType) -> Interned> { - T::get_interned_int_caches() - .sint - .get_or_init(|| SIntType::new_static().intern_sized()) - } } #[derive(Clone, PartialEq, Eq, Debug)] @@ -665,7 +586,7 @@ macro_rules! impl_valueless_op_forward { } macro_rules! impl_int { - ($pretty_name:ident, $name:ident, $generic_name:ident, $value:ident, $SIGNED:literal, $interned_int:ident) => { + ($pretty_name:ident, $name:ident, $generic_name:ident, $value:ident, $SIGNED:literal) => { #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct $name { @@ -1082,7 +1003,7 @@ macro_rules! impl_int { type Output = $name; fn index(&self, width: Width) -> &Self::Output { - Interned::into_inner(Width::Size::$interned_int(width)) + Interned::into_inner(Intern::intern_sized($name::new(width))) } } @@ -1263,22 +1184,8 @@ macro_rules! impl_int { }; } -impl_int!( - UInt, - UIntType, - UIntWithoutGenerics, - UIntValue, - false, - interned_uint -); -impl_int!( - SInt, - SIntType, - SIntWithoutGenerics, - SIntValue, - true, - interned_sint -); +impl_int!(UInt, UIntType, UIntWithoutGenerics, UIntValue, false); +impl_int!(SInt, SIntType, SIntWithoutGenerics, SIntValue, true); impl UInt { /// gets the smallest `UInt` that fits `v` losslessly diff --git a/crates/fayalite/src/intern.rs b/crates/fayalite/src/intern.rs index b78aa59..b68140b 100644 --- a/crates/fayalite/src/intern.rs +++ b/crates/fayalite/src/intern.rs @@ -4,191 +4,68 @@ use crate::{intern::type_map::TypeIdMap, util::DefaultBuildHasher}; use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec}; use hashbrown::HashTable; -use once_cell::race::OnceRef; use serde::{Deserialize, Serialize}; use std::{ any::{Any, TypeId}, borrow::{Borrow, Cow}, - cell::RefCell, cmp::Ordering, ffi::{OsStr, OsString}, fmt, hash::{BuildHasher, Hash, Hasher}, iter::FusedIterator, + marker::PhantomData, ops::Deref, path::{Path, PathBuf}, - sync::RwLock, + sync::{Mutex, RwLock}, }; -mod interner; mod type_map; -/// invariant: T must be zero-sized, `type_id` is unique for every possible T value. -struct LazyInternedLazyInner { - type_id: TypeId, - value: T, +pub trait LazyInternedTrait: Send + Sync + Any { + fn get(&self) -> Interned; } -impl Hash for LazyInternedLazyInner { - fn hash(&self, state: &mut H) { - let Self { type_id, value: _ } = self; - type_id.hash(state); +impl Interned + Send + Sync + Any> + LazyInternedTrait for F +{ + fn get(&self) -> Interned { + self() } } -impl PartialEq for LazyInternedLazyInner { - fn eq(&self, other: &Self) -> bool { - let Self { type_id, value: _ } = self; - *type_id == other.type_id - } -} +#[repr(transparent)] +pub struct LazyInternedFn(pub &'static dyn LazyInternedTrait); -impl Eq for LazyInternedLazyInner {} +impl Copy for LazyInternedFn {} -impl fmt::Debug for LazyInternedLazyInner { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("LazyInternedLazyInner") - .finish_non_exhaustive() - } -} - -impl LazyInternedLazyInner { - const fn new(value: T) -> Self - where - T: Sized, - { - const { assert!(size_of::() == 0) }; - Self { - type_id: TypeId::of::(), - value, - } - } -} - -pub struct LazyInternedLazy( - &'static LazyInternedLazyInner Interned + Send + Sync>, -); - -impl LazyInternedLazy { - pub const fn new_const>>() -> Self { - Self(&const { LazyInternedLazyInner::new(|| V::default().into()) }) - } - pub const fn new_const_default() -> Self - where - Interned: Default, - { - Self::new_const::>() - } - pub fn interned(self) -> Interned { - struct Map(hashbrown::HashTable<(TypeId, &'static (dyn Any + Send + Sync))>); - impl Map { - const EMPTY: Self = Self(hashbrown::HashTable::new()); - fn get( - &self, - lazy_interned_lazy: LazyInternedLazy, - hash: u64, - ) -> Option<&'static Interned> { - let &(_, v) = self.0.find(hash, |v| v.0 == lazy_interned_lazy.0.type_id)?; - let Some(retval) = v.downcast_ref::>() else { - unreachable!(); - }; - Some(retval) - } - fn get_or_insert( - &mut self, - lazy_interned_lazy: LazyInternedLazy, - hash: u64, - v: &'static Interned, - ) -> &'static Interned { - let entry = self - .0 - .entry( - hash, - |&(k, _)| k == lazy_interned_lazy.0.type_id, - |&(k, _)| type_map::TypeIdBuildHasher.hash_one(k), - ) - .or_insert_with(|| (lazy_interned_lazy.0.type_id, v)); - let &(_, v) = entry.get(); - let Some(retval) = v.downcast_ref::>() else { - unreachable!(); - }; - retval - } - } - static GLOBAL_CACHE: RwLock = RwLock::new(Map::EMPTY); - #[cold] - fn insert_in_thread_local_cache( - cache: &RefCell, - this: LazyInternedLazy, - hash: u64, - ) -> Interned { - let read_lock = GLOBAL_CACHE.read().unwrap(); - let v = read_lock.get(this, hash); - drop(read_lock); - let v = v.unwrap_or_else(|| { - let v = Box::leak(Box::new((this.0.value)())); - GLOBAL_CACHE.write().unwrap().get_or_insert(this, hash, v) - }); - *cache.borrow_mut().get_or_insert(this, hash, v) - } - thread_local! { - static THREAD_LOCAL_CACHE: RefCell = const { RefCell::new(Map::EMPTY) }; - } - let hash = type_map::TypeIdBuildHasher.hash_one(self.0.type_id); - THREAD_LOCAL_CACHE.with(|cache| { - let borrow = cache.borrow(); - if let Some(v) = borrow.get(self, hash) { - *v - } else { - drop(borrow); - insert_in_thread_local_cache(cache, self, hash) - } - }) - } -} - -impl Copy for LazyInternedLazy {} - -impl Clone for LazyInternedLazy { +impl Clone for LazyInternedFn { fn clone(&self) -> Self { *self } } -impl Hash for LazyInternedLazy { +impl Hash for LazyInternedFn { fn hash(&self, state: &mut H) { - self.0.hash(state); + self.0.get_ptr_eq_with_type_id().hash(state); } } -impl Eq for LazyInternedLazy {} +impl Eq for LazyInternedFn {} -impl PartialEq for LazyInternedLazy { +impl PartialEq for LazyInternedFn { fn eq(&self, other: &Self) -> bool { - self.0 == other.0 + self.0.get_ptr_eq_with_type_id() == other.0.get_ptr_eq_with_type_id() } } pub enum LazyInterned { Interned(Interned), - Lazy(LazyInternedLazy), + Lazy(LazyInternedFn), } impl LazyInterned { - pub const fn new_const>>() -> Self { - Self::Lazy(LazyInternedLazy::new_const::()) - } - pub const fn new_const_default() -> Self - where - Interned: Default, - { - Self::new_const::>() - } - pub fn interned(self) -> Interned { - match self { - Self::Interned(retval) => retval, - Self::Lazy(retval) => retval.interned(), - } + pub const fn new_lazy(v: &'static dyn LazyInternedTrait) -> Self { + Self::Lazy(LazyInternedFn(v)) } } @@ -200,7 +77,7 @@ impl Clone for LazyInterned { impl Copy for LazyInterned {} -impl Deref for LazyInterned { +impl Deref for LazyInterned { type Target = T; fn deref(&self) -> &Self::Target { @@ -208,9 +85,9 @@ impl Deref for LazyInterned { } } -impl Eq for LazyInterned where Interned: Eq {} +impl Eq for LazyInterned where Interned: Eq {} -impl PartialEq for LazyInterned +impl PartialEq for LazyInterned where Interned: PartialEq, { @@ -219,7 +96,7 @@ where } } -impl Ord for LazyInterned +impl Ord for LazyInterned where Interned: Ord, { @@ -228,7 +105,7 @@ where } } -impl PartialOrd for LazyInterned +impl PartialOrd for LazyInterned where Interned: PartialOrd, { @@ -237,7 +114,7 @@ where } } -impl Hash for LazyInterned +impl Hash for LazyInterned where Interned: Hash, { @@ -246,6 +123,77 @@ where } } +impl LazyInterned { + pub fn interned(self) -> Interned + where + T: Intern, + { + struct MemoizeInterned(PhantomData); + + impl Hash for MemoizeInterned { + fn hash(&self, _state: &mut H) {} + } + + impl PartialEq for MemoizeInterned { + fn eq(&self, _other: &Self) -> bool { + true + } + } + + impl Eq for MemoizeInterned {} + + impl Clone for MemoizeInterned { + fn clone(&self) -> Self { + *self + } + } + + impl Copy for MemoizeInterned {} + + impl MemoizeGeneric for MemoizeInterned { + type InputRef<'a> = LazyInternedFn; + + type InputOwned = LazyInternedFn; + + type InputCow<'a> = LazyInternedFn; + + type Output = Interned; + + fn input_eq(a: Self::InputRef<'_>, b: Self::InputRef<'_>) -> bool { + a == b + } + + fn input_borrow(input: &Self::InputOwned) -> Self::InputRef<'_> { + *input + } + + fn input_cow_into_owned(input: Self::InputCow<'_>) -> Self::InputOwned { + input + } + + fn input_cow_borrow<'a>(input: &'a Self::InputCow<'_>) -> Self::InputRef<'a> { + *input + } + + fn input_cow_from_owned<'a>(input: Self::InputOwned) -> Self::InputCow<'a> { + input + } + + fn input_cow_from_ref(input: Self::InputRef<'_>) -> Self::InputCow<'_> { + input + } + + fn inner(self, input: Self::InputRef<'_>) -> Self::Output { + input.0.get() + } + } + match self { + Self::Interned(retval) => retval, + Self::Lazy(retval) => MemoizeInterned(PhantomData).get(retval), + } + } +} + pub trait InternedCompare { type InternedCompareKey: Ord + Hash; fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey; @@ -645,6 +593,71 @@ impl From> for Cow<'_, } } +struct InternerState { + table: HashTable<&'static T>, + hasher: DefaultBuildHasher, +} + +pub struct Interner { + state: Mutex>, +} + +impl Interner { + fn get() -> &'static Interner { + static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new(); + TYPE_ID_MAP.get_or_insert_default() + } +} + +impl Default for Interner { + fn default() -> Self { + Self { + state: Mutex::new(InternerState { + table: HashTable::new(), + hasher: Default::default(), + }), + } + } +} + +impl Interner { + fn intern) -> &'static T>( + &self, + alloc: F, + value: Cow<'_, T>, + ) -> Interned { + let mut state = self.state.lock().unwrap(); + let InternerState { table, hasher } = &mut *state; + let inner = *table + .entry( + hasher.hash_one(&*value), + |k| **k == *value, + |k| hasher.hash_one(&**k), + ) + .or_insert_with(|| alloc(value)) + .get(); + Interned { inner } + } +} + +impl Interner { + fn intern_sized(&self, value: Cow<'_, T>) -> Interned { + self.intern(|value| Box::leak(Box::new(value.into_owned())), value) + } +} + +impl Interner<[T]> { + fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> { + self.intern(|value| value.into_owned().leak(), value) + } +} + +impl Interner { + fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned { + self.intern(|value| value.into_owned().leak(), value) + } +} + pub struct Interned { inner: &'static T, } @@ -964,7 +977,7 @@ impl Intern for T { where Self: ToOwned, { - interner::Interner::get().intern_sized(this) + Interner::get().intern_sized(this) } } @@ -984,7 +997,7 @@ impl Intern for [T] { where Self: ToOwned, { - interner::Interner::get().intern_slice(this) + Interner::get().intern_slice(this) } } @@ -1004,7 +1017,7 @@ impl Intern for BitSlice { where Self: ToOwned, { - interner::Interner::get().intern_bit_slice(this) + Interner::get().intern_bit_slice(this) } } @@ -1022,17 +1035,10 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy { fn inner(self, input: Self::InputRef<'_>) -> Self::Output; fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output { static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new(); - thread_local! { - static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() }; - } let map: &RwLock<( DefaultBuildHasher, HashTable<(Self, Self::InputOwned, Self::Output)>, - )> = TYPE_ID_MAP_CACHE.with(|cache| { - cache.get_or_insert_with(|| { - TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default())) - }) - }); + )> = TYPE_ID_MAP.get_or_insert_default(); fn hash_eq_key<'a, 'b, T: MemoizeGeneric>( this: &'a T, input: T::InputRef<'b>, @@ -1134,35 +1140,3 @@ pub trait Memoize: 'static + Send + Sync + Hash + Eq + Copy { self.get_cow(Cow::Borrowed(input)) } } - -/// like `once_cell::race::OnceBox` but for `Interned` instead of `Box` -pub struct OnceInterned(OnceRef<'static, T>); - -impl fmt::Debug for OnceInterned { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("OnceInterned").field(&self.get()).finish() - } -} - -impl Default for OnceInterned { - fn default() -> Self { - Self::new() - } -} - -impl OnceInterned { - pub const fn new() -> Self { - Self(OnceRef::new()) - } - pub fn set(&self, v: Interned) -> Result<(), ()> { - self.0.set(v.inner) - } - pub fn get(&self) -> Option> { - self.0.get().map(|inner| Interned { inner }) - } - pub fn get_or_init Interned>(&self, f: F) -> Interned { - Interned { - inner: self.0.get_or_init(|| f().inner), - } - } -} diff --git a/crates/fayalite/src/intern/interner.rs b/crates/fayalite/src/intern/interner.rs deleted file mode 100644 index 4e35636..0000000 --- a/crates/fayalite/src/intern/interner.rs +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// See Notices.txt for copyright information - -use crate::{ - intern::{Interned, type_map::TypeIdMap}, - util::DefaultBuildHasher, -}; -use bitvec::slice::BitSlice; -use hashbrown::HashTable; -use std::{ - borrow::Cow, - hash::{BuildHasher, Hash}, - sync::RwLock, -}; - -struct InternerShard { - table: HashTable<&'static T>, -} - -const LOG2_SHARD_COUNT: u32 = 6; - -fn shard_index_from_hash(hash: u64) -> usize { - // number of bits used for hashbrown's Tag - const HASH_BROWN_TAG_BITS: u32 = 7; - // try to extract bits of the hash that hashbrown isn't using, - // while accounting for some hash functions only returning `usize` bits. - const SHARD_INDEX_START: u32 = usize::BITS - .saturating_sub(HASH_BROWN_TAG_BITS) - .saturating_sub(LOG2_SHARD_COUNT); - let mut shard_index = hash >> SHARD_INDEX_START; - shard_index %= 1 << LOG2_SHARD_COUNT; - shard_index as usize -} - -pub(crate) struct Interner { - shards: [RwLock>; 1 << LOG2_SHARD_COUNT], - hasher: DefaultBuildHasher, -} - -impl Interner { - pub(crate) fn get() -> &'static Interner { - static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new(); - thread_local! { - static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() }; - } - TYPE_ID_MAP_CACHE.with(|cache| { - cache.get_or_insert_with(|| { - TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default())) - }) - }) - } -} - -impl Default for Interner { - fn default() -> Self { - Self { - shards: [const { - RwLock::new(InternerShard { - table: HashTable::new(), - }) - }; _], - hasher: Default::default(), - } - } -} - -impl Interner { - fn intern) -> &'static T>( - &self, - alloc: F, - value: Cow<'_, T>, - ) -> Interned { - let hash = self.hasher.hash_one(&*value); - let shard_index = shard_index_from_hash(hash); - let shard = &self.shards[shard_index]; - let shard_read = shard.read().unwrap(); - let Some(&inner) = shard_read.table.find(hash, |k| **k == *value) else { - drop(shard_read); - return self.intern_cold(alloc, value, hash, shard); - }; - Interned { inner } - } - #[cold] - fn intern_cold) -> &'static T>( - &self, - alloc: F, - value: Cow<'_, T>, - hash: u64, - shard: &RwLock>, - ) -> Interned { - let mut shard = shard.write().unwrap(); - let inner = *shard - .table - .entry(hash, |k| **k == *value, |k| self.hasher.hash_one(&**k)) - .or_insert_with(|| alloc(value)) - .get(); - Interned { inner } - } -} - -impl Interner { - pub(crate) fn intern_sized(&self, value: Cow<'_, T>) -> Interned { - self.intern(|value| Box::leak(Box::new(value.into_owned())), value) - } -} - -impl Interner<[T]> { - pub(crate) fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> { - self.intern(|value| value.into_owned().leak(), value) - } -} - -impl Interner { - pub(crate) fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned { - self.intern(|value| value.into_owned().leak(), value) - } -} diff --git a/crates/fayalite/src/intern/type_map.rs b/crates/fayalite/src/intern/type_map.rs index e31a5bf..945116b 100644 --- a/crates/fayalite/src/intern/type_map.rs +++ b/crates/fayalite/src/intern/type_map.rs @@ -6,7 +6,7 @@ use std::{ sync::RwLock, }; -pub(crate) struct TypeIdHasher(u64); +struct TypeIdHasher(u64); // assumes TypeId has at least 64 bits that is a good hash impl Hasher for TypeIdHasher { @@ -63,7 +63,7 @@ impl Hasher for TypeIdHasher { } } -pub(crate) struct TypeIdBuildHasher; +struct TypeIdBuildHasher; impl BuildHasher for TypeIdBuildHasher { type Hasher = TypeIdHasher; @@ -87,23 +87,20 @@ impl TypeIdMap { fn insert_slow( &self, type_id: TypeId, - make: impl FnOnce() -> &'static (dyn Any + Sync + Send), + make: fn() -> Box, ) -> &'static (dyn Any + Sync + Send) { - let value = make(); + let value = Box::leak(make()); let mut write_guard = self.0.write().unwrap(); *write_guard.entry(type_id).or_insert(value) } - pub(crate) fn get_or_insert_with( - &self, - make: impl FnOnce() -> &'static T, - ) -> &'static 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| *v); drop(read_guard); let retval = match retval { Some(retval) => retval, - None => self.insert_slow(type_id, move || make()), + None => self.insert_slow(type_id, move || Box::new(T::default())), }; retval.downcast_ref().expect("known to have correct TypeId") } diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index d959182..9d1a0e7 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -2396,16 +2396,13 @@ impl ModuleBuilder { #[track_caller] pub fn extern_module_simulation_fn< Args: fmt::Debug + Clone + Hash + Eq + Send + Sync + 'static, - F: Copy + Fn(Args, crate::sim::ExternModuleSimulationState) -> Fut + Send + Sync + 'static, Fut: IntoFuture + 'static, >( &self, args: Args, - f: F, + f: fn(Args, crate::sim::ExternModuleSimulationState) -> Fut, ) { - // use for compile-time side-effect - let _ = crate::sim::SimGeneratorFn::::ASSERT_F_IS_ZERO_SIZED; - self.extern_module_simulation(crate::sim::SimGeneratorFn::new(args, f)); + self.extern_module_simulation(crate::sim::SimGeneratorFn { args, f }); } } diff --git a/crates/fayalite/src/phantom_const.rs b/crates/fayalite/src/phantom_const.rs index fb7be6f..32e9d6b 100644 --- a/crates/fayalite/src/phantom_const.rs +++ b/crates/fayalite/src/phantom_const.rs @@ -4,7 +4,7 @@ use crate::{ expr::{Expr, HdlPartialEqImpl, HdlPartialOrdImpl, ToExpr, ValueType}, int::Bool, - intern::{Intern, Interned, InternedCompare, LazyInterned, Memoize}, + intern::{Intern, Interned, InternedCompare, LazyInterned, LazyInternedTrait, Memoize}, sim::value::{SimValue, ToSimValue, ToSimValueWithType}, source_location::SourceLocation, ty::{ @@ -240,17 +240,11 @@ impl PhantomConst { { Self::new_interned(value.intern_deref()) } - pub const fn new_const>>() -> Self { + pub const fn new_lazy(v: &'static dyn LazyInternedTrait) -> Self { Self { - value: LazyInterned::new_const::(), + value: LazyInterned::new_lazy(v), } } - pub const fn new_const_default() -> Self - where - Interned: Default, - { - Self::new_const::>() - } pub fn get(self) -> Interned { self.value.interned() } @@ -340,7 +334,9 @@ impl StaticType for PhantomConst where Interned: Default, { - const TYPE: Self = Self::new_const_default(); + const TYPE: Self = PhantomConst { + value: LazyInterned::new_lazy(&Interned::::default), + }; const MASK_TYPE: Self::MaskType = (); const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES; const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES; diff --git a/crates/fayalite/src/sim.rs b/crates/fayalite/src/sim.rs index a59a4c7..7068e44 100644 --- a/crates/fayalite/src/sim.rs +++ b/crates/fayalite/src/sim.rs @@ -54,6 +54,7 @@ use std::{ hash::Hash, mem, pin::{Pin, pin}, + ptr, rc::Rc, sync::{Arc, Mutex, MutexGuard}, task::Poll, @@ -4064,48 +4065,13 @@ pub trait ExternModuleSimGenerator: Clone + Eq + Hash + Any + Send + Sync + fmt: fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture + 'a; } -/// Type requirements: `F` must be zero-sized, this guarantees that the function called -/// by `F` is entirely determined by the type `F` and not by its value, allowing us to -/// correctly leave `F` out of the stuff used for `Hash` and `Eq`. -/// -/// Note we can't just use function pointers instead -- comparing them is non-deterministic -/// since Rust will duplicate and/or merge functions, even if those functions happen to have -/// different UB but just happen to compile to the same assembly language: -/// -pub struct SimGeneratorFn Fut, Fut> { - args: Args, - f: F, +pub struct SimGeneratorFn { + pub args: Args, + pub f: fn(Args, ExternModuleSimulationState) -> Fut, } -impl Fut, Fut> - SimGeneratorFn -{ - pub const ASSERT_F_IS_ZERO_SIZED: () = { - if size_of::() != 0 { - panic!( - "F must be zero-sized -- so it must be a closure with no captures or a function item, it can't be a function pointer" - ); - } - }; - pub const fn new(args: Args, f: F) -> Self { - // use for compile-time side-effect - let _ = Self::ASSERT_F_IS_ZERO_SIZED; - Self { args, f } - } - pub const fn args(&self) -> &Args { - &self.args - } - pub const fn f(&self) -> F { - self.f - } -} - -impl Fut, Fut> fmt::Debug - for SimGeneratorFn -{ +impl fmt::Debug for SimGeneratorFn { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // use for compile-time side-effect - let _ = Self::ASSERT_F_IS_ZERO_SIZED; let Self { args, f: _ } = self; f.debug_struct("SimGeneratorFn") .field("args", args) @@ -4114,39 +4080,25 @@ impl Fut, F } } -impl Fut, Fut> Hash - for SimGeneratorFn -{ +impl Hash for SimGeneratorFn { fn hash(&self, state: &mut H) { - // use for compile-time side-effect - let _ = Self::ASSERT_F_IS_ZERO_SIZED; - let Self { args, f: _ } = self; + let Self { args, f } = self; args.hash(state); + f.hash(state); } } -impl Fut, Fut> Eq - for SimGeneratorFn -{ -} +impl Eq for SimGeneratorFn {} -impl Fut, Fut> PartialEq - for SimGeneratorFn -{ +impl PartialEq for SimGeneratorFn { fn eq(&self, other: &Self) -> bool { - // use for compile-time side-effect - let _ = Self::ASSERT_F_IS_ZERO_SIZED; - let Self { args, f: _ } = self; - *args == other.args + let Self { args, f } = self; + *args == other.args && ptr::fn_addr_eq(*f, other.f) } } -impl Fut, Fut> Clone - for SimGeneratorFn -{ +impl Clone for SimGeneratorFn { fn clone(&self) -> Self { - // use for compile-time side-effect - let _ = Self::ASSERT_F_IS_ZERO_SIZED; Self { args: self.args.clone(), f: self.f, @@ -4154,20 +4106,14 @@ impl Fut, Fut> C } } -impl Fut, Fut> Copy - for SimGeneratorFn -{ -} +impl Copy for SimGeneratorFn {} impl< - Args: fmt::Debug + Clone + Eq + Hash + Send + Sync + 'static, - F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut + Send + Sync + 'static, + T: fmt::Debug + Clone + Eq + Hash + Send + Sync + 'static, Fut: IntoFuture + 'static, -> ExternModuleSimGenerator for SimGeneratorFn +> ExternModuleSimGenerator for SimGeneratorFn { fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture + 'a { - // use for compile-time side-effect - let _ = Self::ASSERT_F_IS_ZERO_SIZED; (self.f)(self.args.clone(), sim) } } diff --git a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr index 987cfd0..7191e5e 100644 --- a/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr +++ b/crates/fayalite/tests/ui/simvalue_is_not_internable.stderr @@ -1,95 +1,107 @@ error[E0277]: `Cell` cannot be shared between threads safely - --> tests/ui/simvalue_is_not_internable.rs:11:26 - | - 11 | fn f(v: SimValue<()>) -> Interned> { - | ^^^^^^^^^^^^^^^^^^^^^^ `Cell` cannot be shared between threads safely - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` + --> tests/ui/simvalue_is_not_internable.rs:11:26 + | +11 | fn f(v: SimValue<()>) -> Interned> { + | ^^^^^^^^^^^^^^^^^^^^^^ `Cell` cannot be shared between threads safely + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell` + = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` - --> src/intern.rs - | - | pub struct Interned { - | ^^^^ required by this bound in `Interned` + --> src/intern.rs + | + | pub struct Interned { + | ^^^^ required by this bound in `Interned` error[E0277]: `UnsafeCell>` cannot be shared between threads safely - --> tests/ui/simvalue_is_not_internable.rs:11:26 - | - 11 | fn f(v: SimValue<()>) -> Interned> { - | ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell>` cannot be shared between threads safely - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell>` + --> tests/ui/simvalue_is_not_internable.rs:11:26 + | +11 | fn f(v: SimValue<()>) -> Interned> { + | ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell>` cannot be shared between threads safely + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell>` note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` - --> src/intern.rs - | - | pub struct Interned { - | ^^^^ required by this bound in `Interned` + --> src/intern.rs + | + | pub struct Interned { + | ^^^^ required by this bound in `Interned` error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely - --> tests/ui/simvalue_is_not_internable.rs:11:26 - | - 11 | fn f(v: SimValue<()>) -> Interned> { - | ^^^^^^^^^^^^^^^^^^^^^^ `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Send` is not implemented for `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` + --> tests/ui/simvalue_is_not_internable.rs:11:26 + | +11 | fn f(v: SimValue<()>) -> Interned> { + | ^^^^^^^^^^^^^^^^^^^^^^ `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Send` is not implemented for `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` note: required because it appears within the type `DynSimOnlyValue` - --> src/sim/value/sim_only_value_unsafe.rs - | - | pub struct DynSimOnlyValue(Rc); - | ^^^^^^^^^^^^^^^ + --> src/sim/value/sim_only_value_unsafe.rs + | + | pub struct DynSimOnlyValue(Rc); + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` - --> $RUST/core/src/marker.rs + --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `alloc::raw_vec::RawVec` - --> $RUST/alloc/src/raw_vec/mod.rs + --> $RUST/alloc/src/raw_vec/mod.rs + | + | pub(crate) struct RawVec { + | ^^^^^^ note: required because it appears within the type `Vec` - --> $RUST/alloc/src/vec/mod.rs + --> $RUST/alloc/src/vec/mod.rs + | + | pub struct Vec { + | ^^^ note: required because it appears within the type `OpaqueSimValue` - --> src/ty.rs - | - | pub struct OpaqueSimValue { - | ^^^^^^^^^^^^^^ + --> src/ty.rs + | + | pub struct OpaqueSimValue { + | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` - --> src/sim/value.rs - | - 51 | struct SimValueInner { - | ^^^^^^^^^^^^^ + --> src/sim/value.rs + | + | struct SimValueInner { + | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` - --> $RUST/core/src/cell.rs + --> $RUST/core/src/cell.rs + | + | pub struct UnsafeCell { + | ^^^^^^^^^^ note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` - --> src/intern.rs - | - | pub struct Interned { - | ^^^^ required by this bound in `Interned` + --> src/intern.rs + | + | pub struct Interned { + | ^^^^ required by this bound in `Interned` error[E0277]: the trait bound `fayalite::prelude::SimValue<()>: Intern` is not satisfied --> tests/ui/simvalue_is_not_internable.rs:12:26 @@ -106,214 +118,238 @@ help: consider dereferencing here | + error[E0277]: `Cell` cannot be shared between threads safely - --> tests/ui/simvalue_is_not_internable.rs:12:26 - | - 12 | Intern::intern_sized(v) - | -------------------- ^ `Cell` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` + --> tests/ui/simvalue_is_not_internable.rs:12:26 + | +12 | Intern::intern_sized(v) + | -------------------- ^ `Cell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell` + = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `intern_sized` - --> src/intern.rs - | - | pub trait Intern: Any + Send + Sync { - | ^^^^ required by this bound in `Intern::intern_sized` + --> src/intern.rs + | + | pub trait Intern: Any + Send + Sync { + | ^^^^ required by this bound in `Intern::intern_sized` ... - | fn intern_sized(self) -> Interned - | ------------ required by a bound in this associated function + | fn intern_sized(self) -> Interned + | ------------ required by a bound in this associated function help: consider dereferencing here - | - 12 | Intern::intern_sized(*v) - | + + | +12 | Intern::intern_sized(*v) + | + error[E0277]: `UnsafeCell>` cannot be shared between threads safely - --> tests/ui/simvalue_is_not_internable.rs:12:26 - | - 12 | Intern::intern_sized(v) - | -------------------- ^ `UnsafeCell>` cannot be shared between threads safely - | | - | required by a bound introduced by this call - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell>` + --> tests/ui/simvalue_is_not_internable.rs:12:26 + | +12 | Intern::intern_sized(v) + | -------------------- ^ `UnsafeCell>` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell>` note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `intern_sized` - --> src/intern.rs - | - | pub trait Intern: Any + Send + Sync { - | ^^^^ required by this bound in `Intern::intern_sized` + --> src/intern.rs + | + | pub trait Intern: Any + Send + Sync { + | ^^^^ required by this bound in `Intern::intern_sized` ... - | fn intern_sized(self) -> Interned - | ------------ required by a bound in this associated function + | fn intern_sized(self) -> Interned + | ------------ required by a bound in this associated function help: consider dereferencing here - | - 12 | Intern::intern_sized(*v) - | + + | +12 | Intern::intern_sized(*v) + | + error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely - --> tests/ui/simvalue_is_not_internable.rs:12:26 - | - 12 | Intern::intern_sized(v) - | -------------------- ^ `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely - | | - | required by a bound introduced by this call - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Send` is not implemented for `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` + --> tests/ui/simvalue_is_not_internable.rs:12:26 + | +12 | Intern::intern_sized(v) + | -------------------- ^ `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely + | | + | required by a bound introduced by this call + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Send` is not implemented for `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` note: required because it appears within the type `DynSimOnlyValue` - --> src/sim/value/sim_only_value_unsafe.rs - | - | pub struct DynSimOnlyValue(Rc); - | ^^^^^^^^^^^^^^^ + --> src/sim/value/sim_only_value_unsafe.rs + | + | pub struct DynSimOnlyValue(Rc); + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` - --> $RUST/core/src/marker.rs + --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `alloc::raw_vec::RawVec` - --> $RUST/alloc/src/raw_vec/mod.rs + --> $RUST/alloc/src/raw_vec/mod.rs + | + | pub(crate) struct RawVec { + | ^^^^^^ note: required because it appears within the type `Vec` - --> $RUST/alloc/src/vec/mod.rs + --> $RUST/alloc/src/vec/mod.rs + | + | pub struct Vec { + | ^^^ note: required because it appears within the type `OpaqueSimValue` - --> src/ty.rs - | - | pub struct OpaqueSimValue { - | ^^^^^^^^^^^^^^ + --> src/ty.rs + | + | pub struct OpaqueSimValue { + | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` - --> src/sim/value.rs - | - 51 | struct SimValueInner { - | ^^^^^^^^^^^^^ + --> src/sim/value.rs + | + | struct SimValueInner { + | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` - --> $RUST/core/src/cell.rs + --> $RUST/core/src/cell.rs + | + | pub struct UnsafeCell { + | ^^^^^^^^^^ note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `intern_sized` - --> src/intern.rs - | - | pub trait Intern: Any + Send + Sync { - | ^^^^ required by this bound in `Intern::intern_sized` + --> src/intern.rs + | + | pub trait Intern: Any + Send + Sync { + | ^^^^ required by this bound in `Intern::intern_sized` ... - | fn intern_sized(self) -> Interned - | ------------ required by a bound in this associated function + | fn intern_sized(self) -> Interned + | ------------ required by a bound in this associated function help: consider dereferencing here - | - 12 | Intern::intern_sized(*v) - | + + | +12 | Intern::intern_sized(*v) + | + error[E0277]: `Cell` cannot be shared between threads safely - --> tests/ui/simvalue_is_not_internable.rs:12:5 - | - 12 | Intern::intern_sized(v) - | ^^^^^^^^^^^^^^^^^^^^^^^ `Cell` cannot be shared between threads safely - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell` - = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` + --> tests/ui/simvalue_is_not_internable.rs:12:5 + | +12 | Intern::intern_sized(v) + | ^^^^^^^^^^^^^^^^^^^^^^^ `Cell` cannot be shared between threads safely + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell` + = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` - --> src/intern.rs - | - | pub struct Interned { - | ^^^^ required by this bound in `Interned` + --> src/intern.rs + | + | pub struct Interned { + | ^^^^ required by this bound in `Interned` error[E0277]: `UnsafeCell>` cannot be shared between threads safely - --> tests/ui/simvalue_is_not_internable.rs:12:5 - | - 12 | Intern::intern_sized(v) - | ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell>` cannot be shared between threads safely - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell>` + --> tests/ui/simvalue_is_not_internable.rs:12:5 + | +12 | Intern::intern_sized(v) + | ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell>` cannot be shared between threads safely + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell>` note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` - --> src/intern.rs - | - | pub struct Interned { - | ^^^^ required by this bound in `Interned` + --> src/intern.rs + | + | pub struct Interned { + | ^^^^ required by this bound in `Interned` error[E0277]: `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely - --> tests/ui/simvalue_is_not_internable.rs:12:5 - | - 12 | Intern::intern_sized(v) - | ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely - | - = help: within `fayalite::prelude::SimValue<()>`, the trait `Send` is not implemented for `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` + --> tests/ui/simvalue_is_not_internable.rs:12:5 + | +12 | Intern::intern_sized(v) + | ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` cannot be sent between threads safely + | + = help: within `fayalite::prelude::SimValue<()>`, the trait `Send` is not implemented for `Rc<(dyn value::sim_only_value_unsafe::DynSimOnlyValueTrait + 'static)>` note: required because it appears within the type `DynSimOnlyValue` - --> src/sim/value/sim_only_value_unsafe.rs - | - | pub struct DynSimOnlyValue(Rc); - | ^^^^^^^^^^^^^^^ + --> src/sim/value/sim_only_value_unsafe.rs + | + | pub struct DynSimOnlyValue(Rc); + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `PhantomData` - --> $RUST/core/src/marker.rs + --> $RUST/core/src/marker.rs + | + | pub struct PhantomData; + | ^^^^^^^^^^^ note: required because it appears within the type `alloc::raw_vec::RawVec` - --> $RUST/alloc/src/raw_vec/mod.rs + --> $RUST/alloc/src/raw_vec/mod.rs + | + | pub(crate) struct RawVec { + | ^^^^^^ note: required because it appears within the type `Vec` - --> $RUST/alloc/src/vec/mod.rs + --> $RUST/alloc/src/vec/mod.rs + | + | pub struct Vec { + | ^^^ note: required because it appears within the type `OpaqueSimValue` - --> src/ty.rs - | - | pub struct OpaqueSimValue { - | ^^^^^^^^^^^^^^ + --> src/ty.rs + | + | pub struct OpaqueSimValue { + | ^^^^^^^^^^^^^^ note: required because it appears within the type `value::SimValueInner<()>` - --> src/sim/value.rs - | - 51 | struct SimValueInner { - | ^^^^^^^^^^^^^ + --> src/sim/value.rs + | + | struct SimValueInner { + | ^^^^^^^^^^^^^ note: required because it appears within the type `UnsafeCell>` - --> $RUST/core/src/cell.rs + --> $RUST/core/src/cell.rs + | + | pub struct UnsafeCell { + | ^^^^^^^^^^ note: required because it appears within the type `util::alternating_cell::AlternatingCell>` - --> src/util/alternating_cell.rs - | - 22 | pub(crate) struct AlternatingCell { - | ^^^^^^^^^^^^^^^ + --> src/util/alternating_cell.rs + | + | pub(crate) struct AlternatingCell { + | ^^^^^^^^^^^^^^^ note: required because it appears within the type `fayalite::prelude::SimValue<()>` - --> src/sim/value.rs - | - | pub struct SimValue { - | ^^^^^^^^ + --> src/sim/value.rs + | + | pub struct SimValue { + | ^^^^^^^^ note: required by a bound in `fayalite::intern::Interned` - --> src/intern.rs - | - | pub struct Interned { - | ^^^^ required by this bound in `Interned` + --> src/intern.rs + | + | pub struct Interned { + | ^^^^ required by this bound in `Interned`