Compare commits
No commits in common. "master" and "rocq_hdl" have entirely different histories.
13 changed files with 481 additions and 777 deletions
|
|
@ -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
|
||||
|
|
|
|||
5
Cargo.lock
generated
5
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -109,42 +109,14 @@ impl<T: StaticType, Len: KnownSize> Default for ArrayType<T, Len> {
|
|||
}
|
||||
}
|
||||
|
||||
struct MakeType<T: StaticType>(Interned<T>);
|
||||
|
||||
impl<T: StaticType> From<MakeType<T>> for Interned<T> {
|
||||
fn from(value: MakeType<T>) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: StaticType> Default for MakeType<T> {
|
||||
fn default() -> Self {
|
||||
Self(T::TYPE.intern_sized())
|
||||
}
|
||||
}
|
||||
|
||||
struct MakeMaskType<T: StaticType>(Interned<T::MaskType>);
|
||||
|
||||
impl<T: StaticType> From<MakeMaskType<T>> for Interned<T::MaskType> {
|
||||
fn from(value: MakeMaskType<T>) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: StaticType> Default for MakeMaskType<T> {
|
||||
fn default() -> Self {
|
||||
Self(T::MASK_TYPE.intern_sized())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: StaticType, Len: KnownSize> StaticType for ArrayType<T, Len> {
|
||||
const TYPE: Self = Self {
|
||||
element: LazyInterned::new_const::<MakeType<T>>(),
|
||||
element: LazyInterned::new_lazy(&|| T::TYPE.intern_sized()),
|
||||
len: Len::SIZE,
|
||||
type_properties: Self::TYPE_PROPERTIES,
|
||||
};
|
||||
const MASK_TYPE: Self::MaskType = ArrayType::<T::MaskType, Len> {
|
||||
element: LazyInterned::new_const::<MakeMaskType<T>>(),
|
||||
element: LazyInterned::new_lazy(&|| T::MASK_TYPE.intern_sized()),
|
||||
len: Len::SIZE,
|
||||
type_properties: Self::MASK_TYPE_PROPERTIES,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<DYN_SIZE>;
|
|||
|
||||
trait KnownSizeBaseSealed {}
|
||||
|
||||
impl<const N: usize> KnownSizeBaseSealed for ConstUsize<N> {}
|
||||
impl<const N: usize> 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<Self> {
|
||||
static CACHES: InternedIntCaches<ConstUsize<$size>> = 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<Self>
|
||||
where
|
||||
Self: KnownSize;
|
||||
}
|
||||
|
||||
struct InternedIntCaches<Width: KnownSize> {
|
||||
uint: OnceInterned<UIntType<Width>>,
|
||||
sint: OnceInterned<SIntType<Width>>,
|
||||
}
|
||||
|
||||
impl<Width: KnownSize> InternedIntCaches<Width> {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
uint: OnceInterned::new(),
|
||||
sint: OnceInterned::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(private_bounds)]
|
||||
pub trait KnownSize:
|
||||
GenericConstUsize
|
||||
+ sealed::SizeTypeSealed
|
||||
+ sealed::SizeSealed
|
||||
+ Default
|
||||
+ FillInDefaultedGenerics<Type = Self>
|
||||
+ GetInternedIntCaches
|
||||
{
|
||||
const SIZE: Self;
|
||||
type ArrayMatch<Element: Type>: AsRef<[Expr<Element>]>
|
||||
|
|
@ -177,7 +148,7 @@ pub trait KnownSize:
|
|||
|
||||
impl<const N: usize> KnownSize for ConstUsize<N>
|
||||
where
|
||||
ConstUsize<N>: KnownSizeBase,
|
||||
[(); N]: KnownSizeBase,
|
||||
{
|
||||
const SIZE: Self = Self;
|
||||
type ArrayMatch<Element: Type> = [Expr<Element>; 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<UIntType<Self>>;
|
||||
#[doc(hidden)]
|
||||
fn interned_sint(size_type: Self::SizeType) -> Interned<SIntType<Self>>;
|
||||
}
|
||||
|
||||
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<Element: Type> = Box<[Expr<Element>]>;
|
||||
type ArraySimValue<Element: Type> = Box<[SimValue<Element>]>;
|
||||
|
|
@ -277,36 +242,6 @@ impl Size for DynSize {
|
|||
fn try_from_usize(v: usize) -> Option<Self::SizeType> {
|
||||
Some(v)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn interned_uint(size_type: Self::SizeType) -> Interned<UIntType<Self>> {
|
||||
static CACHED: [OnceInterned<UInt>; MAX_CACHED_INT_WIDTH] =
|
||||
[const { OnceInterned::new() }; _];
|
||||
#[cold]
|
||||
fn intern_cold(width: usize) -> Interned<UInt> {
|
||||
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<SIntType<Self>> {
|
||||
static CACHED: [OnceInterned<SInt>; MAX_CACHED_INT_WIDTH] =
|
||||
[const { OnceInterned::new() }; _];
|
||||
#[cold]
|
||||
fn intern_cold(width: usize) -> Interned<SInt> {
|
||||
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<const VALUE: usize> sealed::SizeSealed for ConstUsize<VALUE> {}
|
||||
|
|
@ -332,20 +267,6 @@ impl<T: KnownSize> Size for T {
|
|||
fn try_from_usize(v: usize) -> Option<Self::SizeType> {
|
||||
if v == T::VALUE { Some(T::SIZE) } else { None }
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn interned_uint(_size_type: Self::SizeType) -> Interned<UIntType<Self>> {
|
||||
T::get_interned_int_caches()
|
||||
.uint
|
||||
.get_or_init(|| UIntType::new_static().intern_sized())
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn interned_sint(_size_type: Self::SizeType) -> Interned<SIntType<Self>> {
|
||||
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<Width: Size = DynSize> {
|
||||
|
|
@ -1082,7 +1003,7 @@ macro_rules! impl_int {
|
|||
type Output = $name<Width::Size>;
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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<T: ?Sized + 'static> {
|
||||
type_id: TypeId,
|
||||
value: T,
|
||||
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
|
||||
fn get(&self) -> Interned<T>;
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static> Hash for LazyInternedLazyInner<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let Self { type_id, value: _ } = self;
|
||||
type_id.hash(state);
|
||||
impl<T: ?Sized + Send + Sync + 'static, F: ?Sized + Fn() -> Interned<T> + Send + Sync + Any>
|
||||
LazyInternedTrait<T> for F
|
||||
{
|
||||
fn get(&self) -> Interned<T> {
|
||||
self()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static> PartialEq for LazyInternedLazyInner<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let Self { type_id, value: _ } = self;
|
||||
*type_id == other.type_id
|
||||
}
|
||||
}
|
||||
#[repr(transparent)]
|
||||
pub struct LazyInternedFn<T: ?Sized + Send + Sync + 'static>(pub &'static dyn LazyInternedTrait<T>);
|
||||
|
||||
impl<T: ?Sized + 'static> Eq for LazyInternedLazyInner<T> {}
|
||||
impl<T: ?Sized + Send + Sync + 'static> Copy for LazyInternedFn<T> {}
|
||||
|
||||
impl<T: ?Sized + 'static> fmt::Debug for LazyInternedLazyInner<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("LazyInternedLazyInner")
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static> LazyInternedLazyInner<T> {
|
||||
const fn new(value: T) -> Self
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
const { assert!(size_of::<T>() == 0) };
|
||||
Self {
|
||||
type_id: TypeId::of::<T>(),
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LazyInternedLazy<T: ?Sized + Send + Sync + 'static>(
|
||||
&'static LazyInternedLazyInner<dyn Fn() -> Interned<T> + Send + Sync>,
|
||||
);
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> LazyInternedLazy<T> {
|
||||
pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
|
||||
Self(&const { LazyInternedLazyInner::new(|| V::default().into()) })
|
||||
}
|
||||
pub const fn new_const_default() -> Self
|
||||
where
|
||||
Interned<T>: Default,
|
||||
{
|
||||
Self::new_const::<Interned<T>>()
|
||||
}
|
||||
pub fn interned(self) -> Interned<T> {
|
||||
struct Map(hashbrown::HashTable<(TypeId, &'static (dyn Any + Send + Sync))>);
|
||||
impl Map {
|
||||
const EMPTY: Self = Self(hashbrown::HashTable::new());
|
||||
fn get<T: ?Sized + Send + Sync + 'static>(
|
||||
&self,
|
||||
lazy_interned_lazy: LazyInternedLazy<T>,
|
||||
hash: u64,
|
||||
) -> Option<&'static Interned<T>> {
|
||||
let &(_, v) = self.0.find(hash, |v| v.0 == lazy_interned_lazy.0.type_id)?;
|
||||
let Some(retval) = v.downcast_ref::<Interned<T>>() else {
|
||||
unreachable!();
|
||||
};
|
||||
Some(retval)
|
||||
}
|
||||
fn get_or_insert<T: ?Sized + Send + Sync + 'static>(
|
||||
&mut self,
|
||||
lazy_interned_lazy: LazyInternedLazy<T>,
|
||||
hash: u64,
|
||||
v: &'static Interned<T>,
|
||||
) -> &'static Interned<T> {
|
||||
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::<Interned<T>>() else {
|
||||
unreachable!();
|
||||
};
|
||||
retval
|
||||
}
|
||||
}
|
||||
static GLOBAL_CACHE: RwLock<Map> = RwLock::new(Map::EMPTY);
|
||||
#[cold]
|
||||
fn insert_in_thread_local_cache<T: ?Sized + Send + Sync + 'static>(
|
||||
cache: &RefCell<Map>,
|
||||
this: LazyInternedLazy<T>,
|
||||
hash: u64,
|
||||
) -> Interned<T> {
|
||||
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<Map> = 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<T: ?Sized + Send + Sync + 'static> Copy for LazyInternedLazy<T> {}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> Clone for LazyInternedLazy<T> {
|
||||
impl<T: ?Sized + Send + Sync + 'static> Clone for LazyInternedFn<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> Hash for LazyInternedLazy<T> {
|
||||
impl<T: ?Sized + Send + Sync + 'static> Hash for LazyInternedFn<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
self.0.get_ptr_eq_with_type_id().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> Eq for LazyInternedLazy<T> {}
|
||||
impl<T: ?Sized + Send + Sync + 'static> Eq for LazyInternedFn<T> {}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> PartialEq for LazyInternedLazy<T> {
|
||||
impl<T: ?Sized + Send + Sync + 'static> PartialEq for LazyInternedFn<T> {
|
||||
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<T: ?Sized + Send + Sync + 'static> {
|
||||
Interned(Interned<T>),
|
||||
Lazy(LazyInternedLazy<T>),
|
||||
Lazy(LazyInternedFn<T>),
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> LazyInterned<T> {
|
||||
pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
|
||||
Self::Lazy(LazyInternedLazy::new_const::<V>())
|
||||
}
|
||||
pub const fn new_const_default() -> Self
|
||||
where
|
||||
Interned<T>: Default,
|
||||
{
|
||||
Self::new_const::<Interned<T>>()
|
||||
}
|
||||
pub fn interned(self) -> Interned<T> {
|
||||
match self {
|
||||
Self::Interned(retval) => retval,
|
||||
Self::Lazy(retval) => retval.interned(),
|
||||
}
|
||||
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self {
|
||||
Self::Lazy(LazyInternedFn(v))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +77,7 @@ impl<T: ?Sized + Sync + Send + 'static> Clone for LazyInterned<T> {
|
|||
|
||||
impl<T: ?Sized + Sync + Send + 'static> Copy for LazyInterned<T> {}
|
||||
|
||||
impl<T: ?Sized + Sync + Send + 'static> Deref for LazyInterned<T> {
|
||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Deref for LazyInterned<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
|
@ -208,9 +85,9 @@ impl<T: ?Sized + Sync + Send + 'static> Deref for LazyInterned<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Sync + Send + 'static> Eq for LazyInterned<T> where Interned<T>: Eq {}
|
||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Eq for LazyInterned<T> where Interned<T>: Eq {}
|
||||
|
||||
impl<T: ?Sized + Sync + Send + 'static> PartialEq for LazyInterned<T>
|
||||
impl<T: ?Sized + Sync + Send + 'static + Intern> PartialEq for LazyInterned<T>
|
||||
where
|
||||
Interned<T>: PartialEq,
|
||||
{
|
||||
|
|
@ -219,7 +96,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Sync + Send + 'static> Ord for LazyInterned<T>
|
||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Ord for LazyInterned<T>
|
||||
where
|
||||
Interned<T>: Ord,
|
||||
{
|
||||
|
|
@ -228,7 +105,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Sync + Send + 'static> PartialOrd for LazyInterned<T>
|
||||
impl<T: ?Sized + Sync + Send + 'static + Intern> PartialOrd for LazyInterned<T>
|
||||
where
|
||||
Interned<T>: PartialOrd,
|
||||
{
|
||||
|
|
@ -237,7 +114,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Sync + Send + 'static> Hash for LazyInterned<T>
|
||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Hash for LazyInterned<T>
|
||||
where
|
||||
Interned<T>: Hash,
|
||||
{
|
||||
|
|
@ -246,6 +123,77 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Sync + Send + 'static> LazyInterned<T> {
|
||||
pub fn interned(self) -> Interned<T>
|
||||
where
|
||||
T: Intern,
|
||||
{
|
||||
struct MemoizeInterned<T: ?Sized + Intern>(PhantomData<T>);
|
||||
|
||||
impl<T: ?Sized + Intern> Hash for MemoizeInterned<T> {
|
||||
fn hash<H: Hasher>(&self, _state: &mut H) {}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Intern> PartialEq for MemoizeInterned<T> {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Intern> Eq for MemoizeInterned<T> {}
|
||||
|
||||
impl<T: ?Sized + Intern> Clone for MemoizeInterned<T> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Intern> Copy for MemoizeInterned<T> {}
|
||||
|
||||
impl<T: ?Sized + Intern> MemoizeGeneric for MemoizeInterned<T> {
|
||||
type InputRef<'a> = LazyInternedFn<T>;
|
||||
|
||||
type InputOwned = LazyInternedFn<T>;
|
||||
|
||||
type InputCow<'a> = LazyInternedFn<T>;
|
||||
|
||||
type Output = Interned<T>;
|
||||
|
||||
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<T: ?Sized + 'static + Send + Sync + ToOwned> From<Interned<T>> for Cow<'_,
|
|||
}
|
||||
}
|
||||
|
||||
struct InternerState<T: ?Sized + 'static + Send + Sync> {
|
||||
table: HashTable<&'static T>,
|
||||
hasher: DefaultBuildHasher,
|
||||
}
|
||||
|
||||
pub struct Interner<T: ?Sized + 'static + Send + Sync> {
|
||||
state: Mutex<InternerState<T>>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
||||
fn get() -> &'static Interner<T> {
|
||||
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
|
||||
TYPE_ID_MAP.get_or_insert_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
state: Mutex::new(InternerState {
|
||||
table: HashTable::new(),
|
||||
hasher: Default::default(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
|
||||
fn intern<F: FnOnce(Cow<'_, T>) -> &'static T>(
|
||||
&self,
|
||||
alloc: F,
|
||||
value: Cow<'_, T>,
|
||||
) -> Interned<T> {
|
||||
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<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<T> {
|
||||
fn intern_sized(&self, value: Cow<'_, T>) -> Interned<T> {
|
||||
self.intern(|value| Box::leak(Box::new(value.into_owned())), value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<[T]> {
|
||||
fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> {
|
||||
self.intern(|value| value.into_owned().leak(), value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Interner<BitSlice> {
|
||||
fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned<BitSlice> {
|
||||
self.intern(|value| value.into_owned().leak(), value)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
inner: &'static T,
|
||||
}
|
||||
|
|
@ -964,7 +977,7 @@ impl<T: Clone + Send + Sync + 'static + Hash + Eq> Intern for T {
|
|||
where
|
||||
Self: ToOwned,
|
||||
{
|
||||
interner::Interner::get().intern_sized(this)
|
||||
Interner::get().intern_sized(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -984,7 +997,7 @@ impl<T: Clone + Send + Sync + 'static + Hash + Eq> 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<T>` instead of `Box<T>`
|
||||
pub struct OnceInterned<T: 'static + Send + Sync>(OnceRef<'static, T>);
|
||||
|
||||
impl<T: 'static + Send + Sync + fmt::Debug> fmt::Debug for OnceInterned<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("OnceInterned").field(&self.get()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static + Send + Sync> Default for OnceInterned<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static + Send + Sync> OnceInterned<T> {
|
||||
pub const fn new() -> Self {
|
||||
Self(OnceRef::new())
|
||||
}
|
||||
pub fn set(&self, v: Interned<T>) -> Result<(), ()> {
|
||||
self.0.set(v.inner)
|
||||
}
|
||||
pub fn get(&self) -> Option<Interned<T>> {
|
||||
self.0.get().map(|inner| Interned { inner })
|
||||
}
|
||||
pub fn get_or_init<F: FnOnce() -> Interned<T>>(&self, f: F) -> Interned<T> {
|
||||
Interned {
|
||||
inner: self.0.get_or_init(|| f().inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T: ?Sized + 'static + Send + Sync> {
|
||||
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<T: ?Sized + 'static + Send + Sync> {
|
||||
shards: [RwLock<InternerShard<T>>; 1 << LOG2_SHARD_COUNT],
|
||||
hasher: DefaultBuildHasher,
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
||||
pub(crate) fn get() -> &'static Interner<T> {
|
||||
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<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
shards: [const {
|
||||
RwLock::new(InternerShard {
|
||||
table: HashTable::new(),
|
||||
})
|
||||
}; _],
|
||||
hasher: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
|
||||
fn intern<F: FnOnce(Cow<'_, T>) -> &'static T>(
|
||||
&self,
|
||||
alloc: F,
|
||||
value: Cow<'_, T>,
|
||||
) -> Interned<T> {
|
||||
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<F: FnOnce(Cow<'_, T>) -> &'static T>(
|
||||
&self,
|
||||
alloc: F,
|
||||
value: Cow<'_, T>,
|
||||
hash: u64,
|
||||
shard: &RwLock<InternerShard<T>>,
|
||||
) -> Interned<T> {
|
||||
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<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<T> {
|
||||
pub(crate) fn intern_sized(&self, value: Cow<'_, T>) -> Interned<T> {
|
||||
self.intern(|value| Box::leak(Box::new(value.into_owned())), value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + 'static + Send + Sync + Hash + Eq> Interner<[T]> {
|
||||
pub(crate) fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> {
|
||||
self.intern(|value| value.into_owned().leak(), value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Interner<BitSlice> {
|
||||
pub(crate) fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned<BitSlice> {
|
||||
self.intern(|value| value.into_owned().leak(), value)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<dyn Any + Sync + Send>,
|
||||
) -> &'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<T: Sized + Any + Send + Sync>(
|
||||
&self,
|
||||
make: impl FnOnce() -> &'static T,
|
||||
) -> &'static T {
|
||||
pub(crate) fn get_or_insert_default<T: Sized + Any + Send + Sync + Default>(&self) -> &T {
|
||||
let type_id = TypeId::of::<T>();
|
||||
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Output = ()> + 'static,
|
||||
>(
|
||||
&self,
|
||||
args: Args,
|
||||
f: F,
|
||||
f: fn(Args, crate::sim::ExternModuleSimulationState) -> Fut,
|
||||
) {
|
||||
// use for compile-time side-effect
|
||||
let _ = crate::sim::SimGeneratorFn::<Args, F, Fut>::ASSERT_F_IS_ZERO_SIZED;
|
||||
self.extern_module_simulation(crate::sim::SimGeneratorFn::new(args, f));
|
||||
self.extern_module_simulation(crate::sim::SimGeneratorFn { args, f });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<T: ?Sized + PhantomConstValue> PhantomConst<T> {
|
|||
{
|
||||
Self::new_interned(value.intern_deref())
|
||||
}
|
||||
pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
|
||||
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self {
|
||||
Self {
|
||||
value: LazyInterned::new_const::<V>(),
|
||||
value: LazyInterned::new_lazy(v),
|
||||
}
|
||||
}
|
||||
pub const fn new_const_default() -> Self
|
||||
where
|
||||
Interned<T>: Default,
|
||||
{
|
||||
Self::new_const::<Interned<T>>()
|
||||
}
|
||||
pub fn get(self) -> Interned<T> {
|
||||
self.value.interned()
|
||||
}
|
||||
|
|
@ -340,7 +334,9 @@ impl<T: ?Sized + PhantomConstValue> StaticType for PhantomConst<T>
|
|||
where
|
||||
Interned<T>: Default,
|
||||
{
|
||||
const TYPE: Self = Self::new_const_default();
|
||||
const TYPE: Self = PhantomConst {
|
||||
value: LazyInterned::new_lazy(&Interned::<T>::default),
|
||||
};
|
||||
const MASK_TYPE: Self::MaskType = ();
|
||||
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
||||
const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
||||
|
|
|
|||
|
|
@ -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<Output = ()> + '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:
|
||||
/// <https://github.com/rust-lang/unsafe-code-guidelines/issues/589#issuecomment-3515424930>
|
||||
pub struct SimGeneratorFn<Args, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> {
|
||||
args: Args,
|
||||
f: F,
|
||||
pub struct SimGeneratorFn<Args, Fut> {
|
||||
pub args: Args,
|
||||
pub f: fn(Args, ExternModuleSimulationState) -> Fut,
|
||||
}
|
||||
|
||||
impl<Args, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut>
|
||||
SimGeneratorFn<Args, F, Fut>
|
||||
{
|
||||
pub const ASSERT_F_IS_ZERO_SIZED: () = {
|
||||
if size_of::<F>() != 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<Args: fmt::Debug, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> fmt::Debug
|
||||
for SimGeneratorFn<Args, F, Fut>
|
||||
{
|
||||
impl<Args: fmt::Debug, Fut> fmt::Debug for SimGeneratorFn<Args, Fut> {
|
||||
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<Args: fmt::Debug, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, F
|
|||
}
|
||||
}
|
||||
|
||||
impl<Args: Hash, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Hash
|
||||
for SimGeneratorFn<Args, F, Fut>
|
||||
{
|
||||
impl<Args: Hash, Fut> Hash for SimGeneratorFn<Args, Fut> {
|
||||
fn hash<H: std::hash::Hasher>(&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<Args: Eq, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Eq
|
||||
for SimGeneratorFn<Args, F, Fut>
|
||||
{
|
||||
}
|
||||
impl<Args: Eq, Fut> Eq for SimGeneratorFn<Args, Fut> {}
|
||||
|
||||
impl<Args: PartialEq, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> PartialEq
|
||||
for SimGeneratorFn<Args, F, Fut>
|
||||
{
|
||||
impl<Args: PartialEq, Fut> PartialEq for SimGeneratorFn<Args, Fut> {
|
||||
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<Args: Clone, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Clone
|
||||
for SimGeneratorFn<Args, F, Fut>
|
||||
{
|
||||
impl<Args: Clone, Fut> Clone for SimGeneratorFn<Args, Fut> {
|
||||
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<Args: Clone, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> C
|
|||
}
|
||||
}
|
||||
|
||||
impl<Args: Copy, F: Copy + Fn(Args, ExternModuleSimulationState) -> Fut, Fut> Copy
|
||||
for SimGeneratorFn<Args, F, Fut>
|
||||
{
|
||||
}
|
||||
impl<Args: Copy, Fut> Copy for SimGeneratorFn<Args, Fut> {}
|
||||
|
||||
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<Output = ()> + 'static,
|
||||
> ExternModuleSimGenerator for SimGeneratorFn<Args, F, Fut>
|
||||
> ExternModuleSimGenerator for SimGeneratorFn<T, Fut>
|
||||
{
|
||||
fn run<'a>(&'a self, sim: ExternModuleSimulationState) -> impl IntoFuture<Output = ()> + 'a {
|
||||
// use for compile-time side-effect
|
||||
let _ = Self::ASSERT_F_IS_ZERO_SIZED;
|
||||
(self.f)(self.args.clone(), sim)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,95 +1,107 @@
|
|||
error[E0277]: `Cell<util::alternating_cell::State>` cannot be shared between threads safely
|
||||
--> tests/ui/simvalue_is_not_internable.rs:11:26
|
||||
|
|
||||
11 | fn f(v: SimValue<()>) -> Interned<SimValue<()>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `Cell<util::alternating_cell::State>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell<util::alternating_cell::State>`
|
||||
= 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<SimValue<()>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `Cell<util::alternating_cell::State>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell<util::alternating_cell::State>`
|
||||
= 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<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
|
||||
error[E0277]: `UnsafeCell<value::SimValueInner<()>>` cannot be shared between threads safely
|
||||
--> tests/ui/simvalue_is_not_internable.rs:11:26
|
||||
|
|
||||
11 | fn f(v: SimValue<()>) -> Interned<SimValue<()>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<value::SimValueInner<()>>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> tests/ui/simvalue_is_not_internable.rs:11:26
|
||||
|
|
||||
11 | fn f(v: SimValue<()>) -> Interned<SimValue<()>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<value::SimValueInner<()>>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell<value::SimValueInner<()>>`
|
||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ 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<SimValue<()>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `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<SimValue<()>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `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<dyn DynSimOnlyValueTrait>);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/sim/value/sim_only_value_unsafe.rs
|
||||
|
|
||||
| pub struct DynSimOnlyValue(Rc<dyn DynSimOnlyValueTrait>);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `PhantomData<DynSimOnlyValue>`
|
||||
--> $RUST/core/src/marker.rs
|
||||
--> $RUST/core/src/marker.rs
|
||||
|
|
||||
| pub struct PhantomData<T: PointeeSized>;
|
||||
| ^^^^^^^^^^^
|
||||
note: required because it appears within the type `alloc::raw_vec::RawVec<DynSimOnlyValue>`
|
||||
--> $RUST/alloc/src/raw_vec/mod.rs
|
||||
--> $RUST/alloc/src/raw_vec/mod.rs
|
||||
|
|
||||
| pub(crate) struct RawVec<T, A: Allocator = Global> {
|
||||
| ^^^^^^
|
||||
note: required because it appears within the type `Vec<DynSimOnlyValue>`
|
||||
--> $RUST/alloc/src/vec/mod.rs
|
||||
--> $RUST/alloc/src/vec/mod.rs
|
||||
|
|
||||
| pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
|
||||
| ^^^
|
||||
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<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| struct SimValueInner<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> $RUST/core/src/cell.rs
|
||||
--> $RUST/core/src/cell.rs
|
||||
|
|
||||
| pub struct UnsafeCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^
|
||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ 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<util::alternating_cell::State>` cannot be shared between threads safely
|
||||
--> tests/ui/simvalue_is_not_internable.rs:12:26
|
||||
|
|
||||
12 | Intern::intern_sized(v)
|
||||
| -------------------- ^ `Cell<util::alternating_cell::State>` 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<util::alternating_cell::State>`
|
||||
= 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<util::alternating_cell::State>` 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<util::alternating_cell::State>`
|
||||
= 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<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
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<Self>
|
||||
| ------------ required by a bound in this associated function
|
||||
| fn intern_sized(self) -> Interned<Self>
|
||||
| ------------ 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<value::SimValueInner<()>>` cannot be shared between threads safely
|
||||
--> tests/ui/simvalue_is_not_internable.rs:12:26
|
||||
|
|
||||
12 | Intern::intern_sized(v)
|
||||
| -------------------- ^ `UnsafeCell<value::SimValueInner<()>>` 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<value::SimValueInner<()>>`
|
||||
--> tests/ui/simvalue_is_not_internable.rs:12:26
|
||||
|
|
||||
12 | Intern::intern_sized(v)
|
||||
| -------------------- ^ `UnsafeCell<value::SimValueInner<()>>` 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<value::SimValueInner<()>>`
|
||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
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<Self>
|
||||
| ------------ required by a bound in this associated function
|
||||
| fn intern_sized(self) -> Interned<Self>
|
||||
| ------------ 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<dyn DynSimOnlyValueTrait>);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/sim/value/sim_only_value_unsafe.rs
|
||||
|
|
||||
| pub struct DynSimOnlyValue(Rc<dyn DynSimOnlyValueTrait>);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `PhantomData<DynSimOnlyValue>`
|
||||
--> $RUST/core/src/marker.rs
|
||||
--> $RUST/core/src/marker.rs
|
||||
|
|
||||
| pub struct PhantomData<T: PointeeSized>;
|
||||
| ^^^^^^^^^^^
|
||||
note: required because it appears within the type `alloc::raw_vec::RawVec<DynSimOnlyValue>`
|
||||
--> $RUST/alloc/src/raw_vec/mod.rs
|
||||
--> $RUST/alloc/src/raw_vec/mod.rs
|
||||
|
|
||||
| pub(crate) struct RawVec<T, A: Allocator = Global> {
|
||||
| ^^^^^^
|
||||
note: required because it appears within the type `Vec<DynSimOnlyValue>`
|
||||
--> $RUST/alloc/src/vec/mod.rs
|
||||
--> $RUST/alloc/src/vec/mod.rs
|
||||
|
|
||||
| pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
|
||||
| ^^^
|
||||
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<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| struct SimValueInner<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> $RUST/core/src/cell.rs
|
||||
--> $RUST/core/src/cell.rs
|
||||
|
|
||||
| pub struct UnsafeCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^
|
||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
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<Self>
|
||||
| ------------ required by a bound in this associated function
|
||||
| fn intern_sized(self) -> Interned<Self>
|
||||
| ------------ 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<util::alternating_cell::State>` cannot be shared between threads safely
|
||||
--> tests/ui/simvalue_is_not_internable.rs:12:5
|
||||
|
|
||||
12 | Intern::intern_sized(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `Cell<util::alternating_cell::State>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell<util::alternating_cell::State>`
|
||||
= 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<util::alternating_cell::State>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `Cell<util::alternating_cell::State>`
|
||||
= 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<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
|
||||
error[E0277]: `UnsafeCell<value::SimValueInner<()>>` cannot be shared between threads safely
|
||||
--> tests/ui/simvalue_is_not_internable.rs:12:5
|
||||
|
|
||||
12 | Intern::intern_sized(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<value::SimValueInner<()>>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> tests/ui/simvalue_is_not_internable.rs:12:5
|
||||
|
|
||||
12 | Intern::intern_sized(v)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<value::SimValueInner<()>>` cannot be shared between threads safely
|
||||
|
|
||||
= help: within `fayalite::prelude::SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell<value::SimValueInner<()>>`
|
||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ 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<dyn DynSimOnlyValueTrait>);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/sim/value/sim_only_value_unsafe.rs
|
||||
|
|
||||
| pub struct DynSimOnlyValue(Rc<dyn DynSimOnlyValueTrait>);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `PhantomData<DynSimOnlyValue>`
|
||||
--> $RUST/core/src/marker.rs
|
||||
--> $RUST/core/src/marker.rs
|
||||
|
|
||||
| pub struct PhantomData<T: PointeeSized>;
|
||||
| ^^^^^^^^^^^
|
||||
note: required because it appears within the type `alloc::raw_vec::RawVec<DynSimOnlyValue>`
|
||||
--> $RUST/alloc/src/raw_vec/mod.rs
|
||||
--> $RUST/alloc/src/raw_vec/mod.rs
|
||||
|
|
||||
| pub(crate) struct RawVec<T, A: Allocator = Global> {
|
||||
| ^^^^^^
|
||||
note: required because it appears within the type `Vec<DynSimOnlyValue>`
|
||||
--> $RUST/alloc/src/vec/mod.rs
|
||||
--> $RUST/alloc/src/vec/mod.rs
|
||||
|
|
||||
| pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
|
||||
| ^^^
|
||||
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<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| struct SimValueInner<T: Type> {
|
||||
| ^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `UnsafeCell<value::SimValueInner<()>>`
|
||||
--> $RUST/core/src/cell.rs
|
||||
--> $RUST/core/src/cell.rs
|
||||
|
|
||||
| pub struct UnsafeCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^
|
||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
22 | pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
--> src/util/alternating_cell.rs
|
||||
|
|
||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `fayalite::prelude::SimValue<()>`
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
--> src/sim/value.rs
|
||||
|
|
||||
| pub struct SimValue<T: Type> {
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `fayalite::intern::Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
--> src/intern.rs
|
||||
|
|
||||
| pub struct Interned<T: ?Sized + 'static + Send + Sync> {
|
||||
| ^^^^ required by this bound in `Interned`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue