forked from libre-chip/fayalite
Compare commits
No commits in common. "91e1b619e8e6c4130cc7e80bd683625b1ec3cd9d" and "5967e812a2a887f44fb49443f06e1fac5cf4e916" have entirely different histories.
91e1b619e8
...
5967e812a2
25 changed files with 154 additions and 584 deletions
56
Cargo.lock
generated
56
Cargo.lock
generated
|
|
@ -2,6 +2,18 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "allocator-api2"
|
name = "allocator-api2"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
|
@ -353,12 +365,6 @@ version = "0.5.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foldhash"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
|
@ -394,13 +400,12 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.2"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"equivalent",
|
|
||||||
"foldhash",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -426,9 +431,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.9.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
|
@ -519,14 +524,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "petgraph"
|
name = "petgraph"
|
||||||
version = "0.8.1"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/programmerjake/petgraph.git?rev=258ea8071209a924b73fe96f9f87a3b7b45cbc9f#258ea8071209a924b73fe96f9f87a3b7b45cbc9f"
|
||||||
checksum = "7a98c6720655620a521dcc722d0ad66cd8afd5d86e34a89ef691c50b7b24de06"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fixedbitset",
|
"fixedbitset",
|
||||||
"hashbrown",
|
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"serde",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -891,3 +893,23 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tap",
|
"tap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,14 @@ blake3 = { version = "1.5.4", features = ["serde"] }
|
||||||
clap = { version = "4.5.9", features = ["derive", "env", "string"] }
|
clap = { version = "4.5.9", features = ["derive", "env", "string"] }
|
||||||
ctor = "0.2.8"
|
ctor = "0.2.8"
|
||||||
eyre = "0.6.12"
|
eyre = "0.6.12"
|
||||||
hashbrown = "0.15.2"
|
hashbrown = "0.14.3"
|
||||||
indexmap = { version = "2.5.0", features = ["serde"] }
|
indexmap = { version = "2.5.0", features = ["serde"] }
|
||||||
jobslot = "0.2.19"
|
jobslot = "0.2.19"
|
||||||
num-bigint = "0.4.6"
|
num-bigint = "0.4.6"
|
||||||
num-traits = "0.2.16"
|
num-traits = "0.2.16"
|
||||||
os_pipe = "1.2.1"
|
os_pipe = "1.2.1"
|
||||||
petgraph = "0.8.1"
|
# TODO: switch back to crates.io once petgraph accepts PR #684 and releases a new version
|
||||||
|
petgraph = { git = "https://github.com/programmerjake/petgraph.git", rev = "258ea8071209a924b73fe96f9f87a3b7b45cbc9f" }
|
||||||
prettyplease = "0.2.20"
|
prettyplease = "0.2.20"
|
||||||
proc-macro2 = "1.0.83"
|
proc-macro2 = "1.0.83"
|
||||||
quote = "1.0.36"
|
quote = "1.0.36"
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ fayalite-visit-gen.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
unstable-doc = []
|
unstable-doc = []
|
||||||
unstable-test-hasher = []
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["unstable-doc"]
|
features = ["unstable-doc"]
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use std::{
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone)]
|
||||||
struct CustomFirrtlAnnotationFieldsImpl {
|
struct CustomFirrtlAnnotationFieldsImpl {
|
||||||
value: serde_json::Map<String, serde_json::Value>,
|
value: serde_json::Map<String, serde_json::Value>,
|
||||||
serialized: Interned<str>,
|
serialized: Interned<str>,
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ use crate::{
|
||||||
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, OpaqueSimValue,
|
impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, OpaqueSimValue,
|
||||||
StaticType, Type, TypeProperties, TypeWithDeref,
|
StaticType, Type, TypeProperties, TypeWithDeref,
|
||||||
},
|
},
|
||||||
util::HashMap,
|
|
||||||
};
|
};
|
||||||
use bitvec::{slice::BitSlice, vec::BitVec};
|
use bitvec::{slice::BitSlice, vec::BitVec};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{fmt, marker::PhantomData};
|
use std::{fmt, marker::PhantomData};
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ impl Default for BundleTypePropertiesBuilder {
|
||||||
impl Bundle {
|
impl Bundle {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn new(fields: Interned<[BundleField]>) -> Self {
|
pub fn new(fields: Interned<[BundleField]>) -> Self {
|
||||||
let mut name_indexes = HashMap::with_capacity_and_hasher(fields.len(), Default::default());
|
let mut name_indexes = HashMap::with_capacity(fields.len());
|
||||||
let mut field_offsets = Vec::with_capacity(fields.len());
|
let mut field_offsets = Vec::with_capacity(fields.len());
|
||||||
let mut type_props_builder = BundleTypePropertiesBuilder::new();
|
let mut type_props_builder = BundleTypePropertiesBuilder::new();
|
||||||
for (index, &BundleField { name, flipped, ty }) in fields.iter().enumerate() {
|
for (index, &BundleField { name, flipped, ty }) in fields.iter().enumerate() {
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ pub struct VerilogArgs {
|
||||||
default_value = "firtool",
|
default_value = "firtool",
|
||||||
env = "FIRTOOL",
|
env = "FIRTOOL",
|
||||||
value_hint = ValueHint::CommandName,
|
value_hint = ValueHint::CommandName,
|
||||||
value_parser = OsStringValueParser::new().try_map(which)
|
value_parser = OsStringValueParser::new().try_map(which::which)
|
||||||
)]
|
)]
|
||||||
pub firtool: PathBuf,
|
pub firtool: PathBuf,
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
|
@ -428,13 +428,6 @@ impl clap::Args for FormalAdjustArgs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn which(v: std::ffi::OsString) -> which::Result<PathBuf> {
|
|
||||||
#[cfg(not(miri))]
|
|
||||||
return which::which(v);
|
|
||||||
#[cfg(miri)]
|
|
||||||
return Ok(Path::new("/").join(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Parser, Clone)]
|
#[derive(Parser, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct FormalArgs {
|
pub struct FormalArgs {
|
||||||
|
|
@ -445,7 +438,7 @@ pub struct FormalArgs {
|
||||||
default_value = "sby",
|
default_value = "sby",
|
||||||
env = "SBY",
|
env = "SBY",
|
||||||
value_hint = ValueHint::CommandName,
|
value_hint = ValueHint::CommandName,
|
||||||
value_parser = OsStringValueParser::new().try_map(which)
|
value_parser = OsStringValueParser::new().try_map(which::which)
|
||||||
)]
|
)]
|
||||||
pub sby: PathBuf,
|
pub sby: PathBuf,
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ use crate::{
|
||||||
CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, StaticType, Type,
|
CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, StaticType, Type,
|
||||||
TypeProperties,
|
TypeProperties,
|
||||||
},
|
},
|
||||||
util::HashMap,
|
|
||||||
};
|
};
|
||||||
use bitvec::{order::Lsb0, slice::BitSlice, view::BitView};
|
use bitvec::{order::Lsb0, slice::BitSlice, view::BitView};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{convert::Infallible, fmt, iter::FusedIterator, sync::Arc};
|
use std::{convert::Infallible, fmt, iter::FusedIterator, sync::Arc};
|
||||||
|
|
||||||
|
|
@ -193,8 +193,7 @@ impl Default for EnumTypePropertiesBuilder {
|
||||||
impl Enum {
|
impl Enum {
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn new(variants: Interned<[EnumVariant]>) -> Self {
|
pub fn new(variants: Interned<[EnumVariant]>) -> Self {
|
||||||
let mut name_indexes =
|
let mut name_indexes = HashMap::with_capacity(variants.len());
|
||||||
HashMap::with_capacity_and_hasher(variants.len(), Default::default());
|
|
||||||
let mut type_props_builder = EnumTypePropertiesBuilder::new();
|
let mut type_props_builder = EnumTypePropertiesBuilder::new();
|
||||||
for (index, EnumVariant { name, ty }) in variants.iter().enumerate() {
|
for (index, EnumVariant { name, ty }) in variants.iter().enumerate() {
|
||||||
if let Some(old_index) = name_indexes.insert(*name, index) {
|
if let Some(old_index) = name_indexes.insert(*name, index) {
|
||||||
|
|
|
||||||
|
|
@ -274,17 +274,6 @@ pub struct Expr<T: Type> {
|
||||||
|
|
||||||
impl<T: Type + fmt::Debug> fmt::Debug for Expr<T> {
|
impl<T: Type + fmt::Debug> fmt::Debug for Expr<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
let Self {
|
|
||||||
__enum,
|
|
||||||
__ty,
|
|
||||||
__flow,
|
|
||||||
} = self;
|
|
||||||
let expr_ty = __ty.canonical();
|
|
||||||
let enum_ty = __enum.to_expr().__ty;
|
|
||||||
assert_eq!(expr_ty, enum_ty, "expr ty mismatch:\nExpr {{\n__enum: {__enum:?},\n__ty: {__ty:?},\n__flow: {__flow:?}\n}}");
|
|
||||||
}
|
|
||||||
self.__enum.fmt(f)
|
self.__enum.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,12 @@ use crate::{
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
util::{
|
util::{
|
||||||
const_str_array_is_strictly_ascending, BitSliceWriteWithBase, DebugAsRawString,
|
const_str_array_is_strictly_ascending, BitSliceWriteWithBase, DebugAsRawString,
|
||||||
GenericConstBool, HashMap, HashSet,
|
GenericConstBool,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bitvec::slice::BitSlice;
|
use bitvec::slice::BitSlice;
|
||||||
use clap::value_parser;
|
use clap::value_parser;
|
||||||
|
use hashbrown::{HashMap, HashSet};
|
||||||
use num_traits::Signed;
|
use num_traits::Signed;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -2621,7 +2622,7 @@ fn export_impl(
|
||||||
indent_depth: &indent_depth,
|
indent_depth: &indent_depth,
|
||||||
indent: " ",
|
indent: " ",
|
||||||
},
|
},
|
||||||
seen_modules: HashSet::default(),
|
seen_modules: HashSet::new(),
|
||||||
unwritten_modules: VecDeque::new(),
|
unwritten_modules: VecDeque::new(),
|
||||||
global_ns,
|
global_ns,
|
||||||
module: ModuleState::default(),
|
module: ModuleState::default(),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
use crate::{intern::type_map::TypeIdMap, util::DefaultBuildHasher};
|
use crate::intern::type_map::TypeIdMap;
|
||||||
use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec};
|
use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec};
|
||||||
use hashbrown::HashTable;
|
use hashbrown::{hash_map::RawEntryMut, HashMap, HashTable};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
|
|
@ -17,7 +17,7 @@ use std::{
|
||||||
sync::{Mutex, RwLock},
|
sync::{Mutex, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod type_map;
|
pub mod type_map;
|
||||||
|
|
||||||
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
|
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
|
||||||
fn get(&self) -> Interned<T>;
|
fn get(&self) -> Interned<T>;
|
||||||
|
|
@ -316,13 +316,8 @@ pub trait Intern: Any + Send + Sync {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InternerState<T: ?Sized + 'static + Send + Sync> {
|
|
||||||
table: HashTable<&'static T>,
|
|
||||||
hasher: DefaultBuildHasher,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Interner<T: ?Sized + 'static + Send + Sync> {
|
pub struct Interner<T: ?Sized + 'static + Send + Sync> {
|
||||||
state: Mutex<InternerState<T>>,
|
map: Mutex<HashMap<&'static T, ()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
||||||
|
|
@ -335,10 +330,7 @@ impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
|
||||||
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: Mutex::new(InternerState {
|
map: Default::default(),
|
||||||
table: HashTable::new(),
|
|
||||||
hasher: Default::default(),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -349,16 +341,17 @@ impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
|
||||||
alloc: F,
|
alloc: F,
|
||||||
value: Cow<'_, T>,
|
value: Cow<'_, T>,
|
||||||
) -> Interned<T> {
|
) -> Interned<T> {
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut map = self.map.lock().unwrap();
|
||||||
let InternerState { table, hasher } = &mut *state;
|
let hasher = map.hasher().clone();
|
||||||
let inner = *table
|
let hash = hasher.hash_one(&*value);
|
||||||
.entry(
|
let inner = match map.raw_entry_mut().from_hash(hash, |k| **k == *value) {
|
||||||
hasher.hash_one(&*value),
|
RawEntryMut::Occupied(entry) => *entry.key(),
|
||||||
|k| **k == *value,
|
RawEntryMut::Vacant(entry) => {
|
||||||
|k| hasher.hash_one(&**k),
|
*entry
|
||||||
)
|
.insert_with_hasher(hash, alloc(value), (), |k| hasher.hash_one(&**k))
|
||||||
.or_insert_with(|| alloc(value))
|
.0
|
||||||
.get();
|
}
|
||||||
|
};
|
||||||
Interned { inner }
|
Interned { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -749,7 +742,7 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy {
|
||||||
fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
|
fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
|
||||||
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
|
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
|
||||||
let map: &RwLock<(
|
let map: &RwLock<(
|
||||||
DefaultBuildHasher,
|
hashbrown::hash_map::DefaultHashBuilder,
|
||||||
HashTable<(Self, Self::InputOwned, Self::Output)>,
|
HashTable<(Self, Self::InputOwned, Self::Output)>,
|
||||||
)> = TYPE_ID_MAP.get_or_insert_default();
|
)> = TYPE_ID_MAP.get_or_insert_default();
|
||||||
fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
|
fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
use hashbrown::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
hash::{BuildHasher, Hasher},
|
hash::{BuildHasher, Hasher},
|
||||||
|
ptr::NonNull,
|
||||||
sync::RwLock,
|
sync::RwLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -73,36 +75,59 @@ impl BuildHasher for TypeIdBuildHasher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct TypeIdMap(
|
struct Value(NonNull<dyn Any + Send + Sync>);
|
||||||
RwLock<hashbrown::HashMap<TypeId, &'static (dyn Any + Send + Sync), TypeIdBuildHasher>>,
|
|
||||||
);
|
impl Value {
|
||||||
|
unsafe fn get_transmute_lifetime<'b>(&self) -> &'b (dyn Any + Send + Sync) {
|
||||||
|
unsafe { &*self.0.as_ptr() }
|
||||||
|
}
|
||||||
|
fn new(v: Box<dyn Any + Send + Sync>) -> Self {
|
||||||
|
unsafe { Self(NonNull::new_unchecked(Box::into_raw(v))) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for Value {}
|
||||||
|
unsafe impl Sync for Value {}
|
||||||
|
|
||||||
|
impl Drop for Value {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { std::ptr::drop_in_place(self.0.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TypeIdMap(RwLock<HashMap<TypeId, Value, TypeIdBuildHasher>>);
|
||||||
|
|
||||||
impl TypeIdMap {
|
impl TypeIdMap {
|
||||||
pub(crate) const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self(RwLock::new(hashbrown::HashMap::with_hasher(
|
Self(RwLock::new(HashMap::with_hasher(TypeIdBuildHasher)))
|
||||||
TypeIdBuildHasher,
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
#[cold]
|
#[cold]
|
||||||
fn insert_slow(
|
unsafe fn insert_slow(
|
||||||
&self,
|
&self,
|
||||||
type_id: TypeId,
|
type_id: TypeId,
|
||||||
make: fn() -> Box<dyn Any + Sync + Send>,
|
make: fn() -> Box<dyn Any + Sync + Send>,
|
||||||
) -> &'static (dyn Any + Sync + Send) {
|
) -> &(dyn Any + Sync + Send) {
|
||||||
let value = Box::leak(make());
|
let value = Value::new(make());
|
||||||
let mut write_guard = self.0.write().unwrap();
|
let mut write_guard = self.0.write().unwrap();
|
||||||
*write_guard.entry(type_id).or_insert(value)
|
unsafe {
|
||||||
|
write_guard
|
||||||
|
.entry(type_id)
|
||||||
|
.or_insert(value)
|
||||||
|
.get_transmute_lifetime()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn get_or_insert_default<T: Sized + Any + Send + Sync + Default>(&self) -> &T {
|
pub fn get_or_insert_default<T: Sized + Any + Send + Sync + Default>(&self) -> &T {
|
||||||
let type_id = TypeId::of::<T>();
|
let type_id = TypeId::of::<T>();
|
||||||
let read_guard = self.0.read().unwrap();
|
let read_guard = self.0.read().unwrap();
|
||||||
let retval = read_guard.get(&type_id).map(|v| *v);
|
let retval = read_guard
|
||||||
|
.get(&type_id)
|
||||||
|
.map(|v| unsafe { Value::get_transmute_lifetime(v) });
|
||||||
drop(read_guard);
|
drop(read_guard);
|
||||||
let retval = match retval {
|
let retval = match retval {
|
||||||
Some(retval) => retval,
|
Some(retval) => retval,
|
||||||
None => self.insert_slow(type_id, move || Box::new(T::default())),
|
None => unsafe { self.insert_slow(type_id, move || Box::new(T::default())) },
|
||||||
};
|
};
|
||||||
retval.downcast_ref().expect("known to have correct TypeId")
|
unsafe { &*(retval as *const dyn Any as *const T) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -470,7 +470,7 @@ pub enum ReadUnderWrite {
|
||||||
Undefined,
|
Undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
struct MemImpl<Element: Type, Len: Size, P> {
|
struct MemImpl<Element: Type, Len: Size, P> {
|
||||||
scoped_name: ScopedNameId,
|
scoped_name: ScopedNameId,
|
||||||
source_location: SourceLocation,
|
source_location: SourceLocation,
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ use crate::{
|
||||||
sim::{ExternModuleSimGenerator, ExternModuleSimulation},
|
sim::{ExternModuleSimGenerator, ExternModuleSimulation},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
util::{HashMap, HashSet, ScopedRef},
|
util::ScopedRef,
|
||||||
wire::{IncompleteWire, Wire},
|
wire::{IncompleteWire, Wire},
|
||||||
};
|
};
|
||||||
use hashbrown::hash_map::Entry;
|
use hashbrown::{hash_map::Entry, HashMap, HashSet};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
|
|
@ -1498,7 +1498,7 @@ impl TargetState {
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
CanonicalType::PhantomConst(_) => TargetStateInner::Decomposed {
|
CanonicalType::PhantomConst(_) => TargetStateInner::Decomposed {
|
||||||
subtargets: HashMap::default(),
|
subtargets: HashMap::new(),
|
||||||
},
|
},
|
||||||
CanonicalType::Array(ty) => TargetStateInner::Decomposed {
|
CanonicalType::Array(ty) => TargetStateInner::Decomposed {
|
||||||
subtargets: (0..ty.len())
|
subtargets: (0..ty.len())
|
||||||
|
|
@ -1864,7 +1864,7 @@ impl<T: BundleType> Module<T> {
|
||||||
AssertValidityState {
|
AssertValidityState {
|
||||||
module: self.canonical(),
|
module: self.canonical(),
|
||||||
blocks: vec![],
|
blocks: vec![],
|
||||||
target_states: HashMap::with_capacity_and_hasher(64, Default::default()),
|
target_states: HashMap::with_capacity(64),
|
||||||
}
|
}
|
||||||
.assert_validity();
|
.assert_validity();
|
||||||
}
|
}
|
||||||
|
|
@ -2125,8 +2125,8 @@ impl ModuleBuilder {
|
||||||
incomplete_declarations: vec![],
|
incomplete_declarations: vec![],
|
||||||
stmts: vec![],
|
stmts: vec![],
|
||||||
}],
|
}],
|
||||||
annotations_map: HashMap::default(),
|
annotations_map: HashMap::new(),
|
||||||
memory_map: HashMap::default(),
|
memory_map: HashMap::new(),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
@ -2136,7 +2136,7 @@ impl ModuleBuilder {
|
||||||
impl_: RefCell::new(ModuleBuilderImpl {
|
impl_: RefCell::new(ModuleBuilderImpl {
|
||||||
body,
|
body,
|
||||||
io: vec![],
|
io: vec![],
|
||||||
io_indexes: HashMap::default(),
|
io_indexes: HashMap::new(),
|
||||||
module_annotations: vec![],
|
module_annotations: vec![],
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reset::{ResetType, ResetTypeDispatch},
|
reset::{ResetType, ResetTypeDispatch},
|
||||||
util::{HashMap, HashSet},
|
|
||||||
};
|
};
|
||||||
use hashbrown::hash_map::Entry;
|
use hashbrown::{hash_map::Entry, HashMap, HashSet};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use petgraph::unionfind::UnionFind;
|
use petgraph::unionfind::UnionFind;
|
||||||
use std::{fmt, marker::PhantomData};
|
use std::{fmt, marker::PhantomData};
|
||||||
|
|
@ -2252,9 +2251,9 @@ pub fn deduce_resets(
|
||||||
fallback_to_sync_reset: bool,
|
fallback_to_sync_reset: bool,
|
||||||
) -> Result<Interned<Module<Bundle>>, DeduceResetsError> {
|
) -> Result<Interned<Module<Bundle>>, DeduceResetsError> {
|
||||||
let mut state = State {
|
let mut state = State {
|
||||||
modules_added_to_graph: HashSet::default(),
|
modules_added_to_graph: HashSet::new(),
|
||||||
substituted_modules: HashMap::default(),
|
substituted_modules: HashMap::new(),
|
||||||
expr_resets: HashMap::default(),
|
expr_resets: HashMap::new(),
|
||||||
reset_graph: ResetGraph::default(),
|
reset_graph: ResetGraph::default(),
|
||||||
fallback_to_sync_reset,
|
fallback_to_sync_reset,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
util::HashMap,
|
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
};
|
};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SimplifyEnumsError {
|
pub enum SimplifyEnumsError {
|
||||||
|
|
@ -965,8 +965,8 @@ pub fn simplify_enums(
|
||||||
kind: SimplifyEnumsKind,
|
kind: SimplifyEnumsKind,
|
||||||
) -> Result<Interned<Module<Bundle>>, SimplifyEnumsError> {
|
) -> Result<Interned<Module<Bundle>>, SimplifyEnumsError> {
|
||||||
module.fold(&mut State {
|
module.fold(&mut State {
|
||||||
enum_types: HashMap::default(),
|
enum_types: HashMap::new(),
|
||||||
replacement_mem_ports: HashMap::default(),
|
replacement_mem_ports: HashMap::new(),
|
||||||
kind,
|
kind,
|
||||||
module_state_stack: vec![],
|
module_state_stack: vec![],
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,11 @@ use crate::{
|
||||||
},
|
},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{CanonicalType, Type},
|
ty::{CanonicalType, Type},
|
||||||
util::{HashMap, MakeMutSlice},
|
util::MakeMutSlice,
|
||||||
wire::Wire,
|
wire::Wire,
|
||||||
};
|
};
|
||||||
use bitvec::{slice::BitSlice, vec::BitVec};
|
use bitvec::{slice::BitSlice, vec::BitVec};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use std::{
|
use std::{
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
fmt::Write,
|
fmt::Write,
|
||||||
|
|
@ -896,7 +897,7 @@ impl Folder for State {
|
||||||
module,
|
module,
|
||||||
ModuleState {
|
ModuleState {
|
||||||
output_module: None,
|
output_module: None,
|
||||||
memories: HashMap::default(),
|
memories: HashMap::new(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let mut this = PushedState::push_module(self, module);
|
let mut this = PushedState::push_module(self, module);
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,10 @@ use crate::{
|
||||||
value::SimValue,
|
value::SimValue,
|
||||||
},
|
},
|
||||||
ty::StaticType,
|
ty::StaticType,
|
||||||
util::{BitSliceWriteWithBase, DebugAsDisplay, HashMap, HashSet},
|
util::{BitSliceWriteWithBase, DebugAsDisplay},
|
||||||
};
|
};
|
||||||
use bitvec::{bits, order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView};
|
use bitvec::{bits, order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView};
|
||||||
|
use hashbrown::{HashMap, HashSet};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use num_traits::{Signed, Zero};
|
use num_traits::{Signed, Zero};
|
||||||
use petgraph::{
|
use petgraph::{
|
||||||
|
|
@ -579,9 +580,8 @@ impl Assignments {
|
||||||
big_slots,
|
big_slots,
|
||||||
}) = self.slot_readers();
|
}) = self.slot_readers();
|
||||||
AssignmentsElements {
|
AssignmentsElements {
|
||||||
node_indexes: HashMap::with_capacity_and_hasher(
|
node_indexes: HashMap::with_capacity(
|
||||||
self.assignments().len() + small_slots.len() + big_slots.len(),
|
self.assignments().len() + small_slots.len() + big_slots.len(),
|
||||||
Default::default(),
|
|
||||||
),
|
),
|
||||||
nodes: self.node_references(),
|
nodes: self.node_references(),
|
||||||
edges: self.edge_references(),
|
edges: self.edge_references(),
|
||||||
|
|
@ -1022,16 +1022,6 @@ impl VisitMap<AssignmentOrSlotIndex> for AssignmentsVisitMap {
|
||||||
AssignmentOrSlotIndex::BigSlot(slot) => self.slots.contains(slot),
|
AssignmentOrSlotIndex::BigSlot(slot) => self.slots.contains(slot),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unvisit(&mut self, n: AssignmentOrSlotIndex) -> bool {
|
|
||||||
match n {
|
|
||||||
AssignmentOrSlotIndex::AssignmentIndex(assignment_index) => {
|
|
||||||
mem::replace(&mut self.assignments[assignment_index], false)
|
|
||||||
}
|
|
||||||
AssignmentOrSlotIndex::SmallSlot(slot) => self.slots.remove(slot),
|
|
||||||
AssignmentOrSlotIndex::BigSlot(slot) => self.slots.remove(slot),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Visitable for Assignments {
|
impl Visitable for Assignments {
|
||||||
|
|
@ -1686,18 +1676,18 @@ impl Compiler {
|
||||||
insns: Insns::new(),
|
insns: Insns::new(),
|
||||||
original_base_module,
|
original_base_module,
|
||||||
base_module,
|
base_module,
|
||||||
modules: HashMap::default(),
|
modules: HashMap::new(),
|
||||||
extern_modules: Vec::new(),
|
extern_modules: Vec::new(),
|
||||||
compiled_values: HashMap::default(),
|
compiled_values: HashMap::new(),
|
||||||
compiled_exprs: HashMap::default(),
|
compiled_exprs: HashMap::new(),
|
||||||
compiled_exprs_to_values: HashMap::default(),
|
compiled_exprs_to_values: HashMap::new(),
|
||||||
decl_conditions: HashMap::default(),
|
decl_conditions: HashMap::new(),
|
||||||
compiled_values_to_dyn_array_indexes: HashMap::default(),
|
compiled_values_to_dyn_array_indexes: HashMap::new(),
|
||||||
compiled_value_bool_dest_is_small_map: HashMap::default(),
|
compiled_value_bool_dest_is_small_map: HashMap::new(),
|
||||||
assignments: Assignments::default(),
|
assignments: Assignments::default(),
|
||||||
clock_triggers: Vec::new(),
|
clock_triggers: Vec::new(),
|
||||||
compiled_value_to_clock_trigger_map: HashMap::default(),
|
compiled_value_to_clock_trigger_map: HashMap::new(),
|
||||||
enum_discriminants: HashMap::default(),
|
enum_discriminants: HashMap::new(),
|
||||||
registers: Vec::new(),
|
registers: Vec::new(),
|
||||||
traces: SimTraces(Vec::new()),
|
traces: SimTraces(Vec::new()),
|
||||||
memories: Vec::new(),
|
memories: Vec::new(),
|
||||||
|
|
@ -5793,7 +5783,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
struct SimTrace<K, S> {
|
struct SimTrace<K, S> {
|
||||||
kind: K,
|
kind: K,
|
||||||
state: S,
|
state: S,
|
||||||
|
|
@ -5986,8 +5976,8 @@ impl SimulationModuleState {
|
||||||
fn new(base_targets: impl IntoIterator<Item = (Target, CompiledValue<CanonicalType>)>) -> Self {
|
fn new(base_targets: impl IntoIterator<Item = (Target, CompiledValue<CanonicalType>)>) -> Self {
|
||||||
let mut retval = Self {
|
let mut retval = Self {
|
||||||
base_targets: Vec::new(),
|
base_targets: Vec::new(),
|
||||||
uninitialized_ios: HashMap::default(),
|
uninitialized_ios: HashMap::new(),
|
||||||
io_targets: HashMap::default(),
|
io_targets: HashMap::new(),
|
||||||
did_initial_settle: false,
|
did_initial_settle: false,
|
||||||
};
|
};
|
||||||
for (base_target, value) in base_targets {
|
for (base_target, value) in base_targets {
|
||||||
|
|
@ -6217,7 +6207,7 @@ impl Default for EarliestWaitTargets {
|
||||||
Self {
|
Self {
|
||||||
settle: false,
|
settle: false,
|
||||||
instant: None,
|
instant: None,
|
||||||
changes: HashMap::default(),
|
changes: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6227,14 +6217,14 @@ impl EarliestWaitTargets {
|
||||||
Self {
|
Self {
|
||||||
settle: true,
|
settle: true,
|
||||||
instant: None,
|
instant: None,
|
||||||
changes: HashMap::default(),
|
changes: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn instant(instant: SimInstant) -> Self {
|
fn instant(instant: SimInstant) -> Self {
|
||||||
Self {
|
Self {
|
||||||
settle: false,
|
settle: false,
|
||||||
instant: Some(instant),
|
instant: Some(instant),
|
||||||
changes: HashMap::default(),
|
changes: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,10 @@ use crate::{
|
||||||
intern::{Intern, Interned, Memoize},
|
intern::{Intern, Interned, Memoize},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::CanonicalType,
|
ty::CanonicalType,
|
||||||
util::{get_many_mut, HashMap, HashSet},
|
util::get_many_mut,
|
||||||
};
|
};
|
||||||
use bitvec::{boxed::BitBox, slice::BitSlice};
|
use bitvec::{boxed::BitBox, slice::BitSlice};
|
||||||
|
use hashbrown::{HashMap, HashSet};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||||
use std::{
|
use std::{
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,9 @@ use crate::{
|
||||||
TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId, TraceScope, TraceSyncReset,
|
TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId, TraceScope, TraceSyncReset,
|
||||||
TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
|
TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
|
||||||
},
|
},
|
||||||
util::HashMap,
|
|
||||||
};
|
};
|
||||||
use bitvec::{order::Lsb0, slice::BitSlice};
|
use bitvec::{order::Lsb0, slice::BitSlice};
|
||||||
use hashbrown::hash_map::Entry;
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Write as _},
|
fmt::{self, Write as _},
|
||||||
io, mem,
|
io, mem,
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
use crate::{
|
use crate::{
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned},
|
||||||
util::{DebugAsDisplay, HashMap},
|
util::DebugAsDisplay,
|
||||||
};
|
};
|
||||||
|
use hashbrown::HashMap;
|
||||||
use std::{cell::RefCell, fmt, num::NonZeroUsize, panic, path::Path};
|
use std::{cell::RefCell, fmt, num::NonZeroUsize, panic, path::Path};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
@ -96,7 +97,7 @@ impl NormalizeFilesForTestsState {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
test_position: panic::Location::caller(),
|
test_position: panic::Location::caller(),
|
||||||
file_pattern_matches: HashMap::default(),
|
file_pattern_matches: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +143,7 @@ impl From<&'_ panic::Location<'_>> for SourceLocation {
|
||||||
map.entry_ref(file)
|
map.entry_ref(file)
|
||||||
.or_insert_with(|| NormalizedFileForTestState {
|
.or_insert_with(|| NormalizedFileForTestState {
|
||||||
file_name_id: NonZeroUsize::new(len + 1).unwrap(),
|
file_name_id: NonZeroUsize::new(len + 1).unwrap(),
|
||||||
positions_map: HashMap::default(),
|
positions_map: HashMap::new(),
|
||||||
});
|
});
|
||||||
file_str = m.generate_file_name(file_state.file_name_id);
|
file_str = m.generate_file_name(file_state.file_name_id);
|
||||||
file = &file_str;
|
file = &file_str;
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::{FormalArgs, FormalMode, FormalOutput, RunPhase},
|
cli::{FormalArgs, FormalMode, FormalOutput, RunPhase},
|
||||||
firrtl::ExportOptions,
|
firrtl::ExportOptions,
|
||||||
util::HashMap,
|
|
||||||
};
|
};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use hashbrown::HashMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Write,
|
fmt::Write,
|
||||||
|
|
@ -87,7 +87,7 @@ fn get_assert_formal_target_path(test_name: &dyn std::fmt::Display) -> PathBuf {
|
||||||
let index = *DIRS
|
let index = *DIRS
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_or_insert_with(HashMap::default)
|
.get_or_insert_with(HashMap::new)
|
||||||
.entry_ref(&dir)
|
.entry_ref(&dir)
|
||||||
.and_modify(|v| *v += 1)
|
.and_modify(|v| *v += 1)
|
||||||
.or_insert(0);
|
.or_insert(0);
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,6 @@ mod const_usize;
|
||||||
mod misc;
|
mod misc;
|
||||||
mod scoped_ref;
|
mod scoped_ref;
|
||||||
pub(crate) mod streaming_read_utf8;
|
pub(crate) mod streaming_read_utf8;
|
||||||
mod test_hasher;
|
|
||||||
|
|
||||||
// allow easily switching the hasher crate-wide for testing
|
|
||||||
#[cfg(feature = "unstable-test-hasher")]
|
|
||||||
pub type DefaultBuildHasher = test_hasher::DefaultBuildHasher;
|
|
||||||
#[cfg(not(feature = "unstable-test-hasher"))]
|
|
||||||
pub(crate) type DefaultBuildHasher = hashbrown::DefaultHashBuilder;
|
|
||||||
|
|
||||||
pub(crate) type HashMap<K, V> = hashbrown::HashMap<K, V, DefaultBuildHasher>;
|
|
||||||
pub(crate) type HashSet<T> = hashbrown::HashSet<T, DefaultBuildHasher>;
|
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use const_bool::{ConstBool, ConstBoolDispatch, ConstBoolDispatchTag, GenericConstBool};
|
pub use const_bool::{ConstBool, ConstBoolDispatch, ConstBoolDispatchTag, GenericConstBool};
|
||||||
|
|
|
||||||
|
|
@ -1,240 +0,0 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
||||||
// See Notices.txt for copyright information
|
|
||||||
#![cfg(feature = "unstable-test-hasher")]
|
|
||||||
|
|
||||||
use std::{
|
|
||||||
fmt::Write as _,
|
|
||||||
hash::{BuildHasher, Hash, Hasher},
|
|
||||||
io::Write as _,
|
|
||||||
marker::PhantomData,
|
|
||||||
sync::LazyLock,
|
|
||||||
};
|
|
||||||
|
|
||||||
type BoxDynHasher = Box<dyn Hasher + Send + Sync>;
|
|
||||||
type BoxDynBuildHasher = Box<dyn DynBuildHasherTrait + Send + Sync>;
|
|
||||||
type BoxDynMakeBuildHasher = Box<dyn Fn() -> BoxDynBuildHasher + Send + Sync>;
|
|
||||||
|
|
||||||
trait TryGetDynBuildHasher: Copy {
|
|
||||||
type Type;
|
|
||||||
fn try_get_make_build_hasher(self) -> Option<BoxDynMakeBuildHasher>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> TryGetDynBuildHasher for PhantomData<T> {
|
|
||||||
type Type = T;
|
|
||||||
fn try_get_make_build_hasher(self) -> Option<BoxDynMakeBuildHasher> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default + BuildHasher<Hasher: Send + Sync + 'static> + Send + Sync + 'static + Clone>
|
|
||||||
TryGetDynBuildHasher for &'_ PhantomData<T>
|
|
||||||
{
|
|
||||||
type Type = T;
|
|
||||||
fn try_get_make_build_hasher(self) -> Option<BoxDynMakeBuildHasher> {
|
|
||||||
Some(Box::new(|| Box::<DynBuildHasher<T>>::default()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
|
||||||
struct DynBuildHasher<T>(T);
|
|
||||||
|
|
||||||
trait DynBuildHasherTrait: BuildHasher<Hasher = BoxDynHasher> {
|
|
||||||
fn clone_dyn_build_hasher(&self) -> BoxDynBuildHasher;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<BH: BuildHasher<Hasher: Send + Sync + 'static>> BuildHasher for DynBuildHasher<BH> {
|
|
||||||
type Hasher = BoxDynHasher;
|
|
||||||
|
|
||||||
fn build_hasher(&self) -> Self::Hasher {
|
|
||||||
Box::new(self.0.build_hasher())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash_one<T: Hash>(&self, x: T) -> u64 {
|
|
||||||
self.0.hash_one(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<BH> DynBuildHasherTrait for DynBuildHasher<BH>
|
|
||||||
where
|
|
||||||
Self: Clone + BuildHasher<Hasher = BoxDynHasher> + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
fn clone_dyn_build_hasher(&self) -> BoxDynBuildHasher {
|
|
||||||
Box::new(self.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DefaultBuildHasher(BoxDynBuildHasher);
|
|
||||||
|
|
||||||
impl Clone for DefaultBuildHasher {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
DefaultBuildHasher(self.0.clone_dyn_build_hasher())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ENV_VAR_NAME: &'static str = "FAYALITE_TEST_HASHER";
|
|
||||||
|
|
||||||
struct EnvVarValue {
|
|
||||||
key: &'static str,
|
|
||||||
try_get_make_build_hasher: fn() -> Option<BoxDynMakeBuildHasher>,
|
|
||||||
description: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! env_var_value {
|
|
||||||
(
|
|
||||||
key: $key:literal,
|
|
||||||
build_hasher: $build_hasher:ty,
|
|
||||||
description: $description:literal,
|
|
||||||
) => {
|
|
||||||
EnvVarValue {
|
|
||||||
key: $key,
|
|
||||||
try_get_make_build_hasher: || {
|
|
||||||
// use rust method resolution to detect if $build_hasher is usable
|
|
||||||
// (e.g. hashbrown's hasher won't be usable without the right feature enabled)
|
|
||||||
(&PhantomData::<DynBuildHasher<$build_hasher>>).try_get_make_build_hasher()
|
|
||||||
},
|
|
||||||
description: $description,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct AlwaysZeroHasher;
|
|
||||||
|
|
||||||
impl Hasher for AlwaysZeroHasher {
|
|
||||||
fn write(&mut self, _bytes: &[u8]) {}
|
|
||||||
fn finish(&self) -> u64 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ENV_VAR_VALUES: &'static [EnvVarValue] = &[
|
|
||||||
env_var_value! {
|
|
||||||
key: "std",
|
|
||||||
build_hasher: std::hash::RandomState,
|
|
||||||
description: "use std::hash::RandomState",
|
|
||||||
},
|
|
||||||
env_var_value! {
|
|
||||||
key: "hashbrown",
|
|
||||||
build_hasher: hashbrown::DefaultHashBuilder,
|
|
||||||
description: "use hashbrown's DefaultHashBuilder",
|
|
||||||
},
|
|
||||||
env_var_value! {
|
|
||||||
key: "always_zero",
|
|
||||||
build_hasher: std::hash::BuildHasherDefault<AlwaysZeroHasher>,
|
|
||||||
description: "use a hasher that always returns 0 for all hashes,\n \
|
|
||||||
this is useful for checking that PartialEq impls are correct",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
fn report_bad_env_var(msg: impl std::fmt::Display) -> ! {
|
|
||||||
let mut msg = format!("{ENV_VAR_NAME}: {msg}\n");
|
|
||||||
for &EnvVarValue {
|
|
||||||
key,
|
|
||||||
try_get_make_build_hasher,
|
|
||||||
description,
|
|
||||||
} in ENV_VAR_VALUES
|
|
||||||
{
|
|
||||||
let availability = match try_get_make_build_hasher() {
|
|
||||||
Some(_) => "available",
|
|
||||||
None => "unavailable",
|
|
||||||
};
|
|
||||||
writeln!(msg, "{key}: ({availability})\n {description}").expect("can't fail");
|
|
||||||
}
|
|
||||||
std::io::stderr()
|
|
||||||
.write_all(msg.as_bytes())
|
|
||||||
.expect("should be able to write to stderr");
|
|
||||||
std::process::abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DefaultBuildHasher {
|
|
||||||
fn default() -> Self {
|
|
||||||
static DEFAULT_FN: LazyLock<BoxDynMakeBuildHasher> = LazyLock::new(|| {
|
|
||||||
let var = std::env::var_os(ENV_VAR_NAME);
|
|
||||||
let var = var.as_deref().unwrap_or("std".as_ref());
|
|
||||||
for &EnvVarValue {
|
|
||||||
key,
|
|
||||||
try_get_make_build_hasher,
|
|
||||||
description: _,
|
|
||||||
} in ENV_VAR_VALUES
|
|
||||||
{
|
|
||||||
if var.as_encoded_bytes().eq_ignore_ascii_case(key.as_bytes()) {
|
|
||||||
return try_get_make_build_hasher().unwrap_or_else(|| {
|
|
||||||
report_bad_env_var(format_args!(
|
|
||||||
"unavailable hasher: {key} (is the appropriate feature enabled?)"
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
report_bad_env_var(format_args!("unrecognized hasher: {var:?}"));
|
|
||||||
});
|
|
||||||
Self(DEFAULT_FN())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DefaultHasher(BoxDynHasher);
|
|
||||||
|
|
||||||
impl BuildHasher for DefaultBuildHasher {
|
|
||||||
type Hasher = DefaultHasher;
|
|
||||||
|
|
||||||
fn build_hasher(&self) -> Self::Hasher {
|
|
||||||
DefaultHasher(self.0.build_hasher())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hasher for DefaultHasher {
|
|
||||||
fn finish(&self) -> u64 {
|
|
||||||
self.0.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write(&mut self, bytes: &[u8]) {
|
|
||||||
self.0.write(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u8(&mut self, i: u8) {
|
|
||||||
self.0.write_u8(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u16(&mut self, i: u16) {
|
|
||||||
self.0.write_u16(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u32(&mut self, i: u32) {
|
|
||||||
self.0.write_u32(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u64(&mut self, i: u64) {
|
|
||||||
self.0.write_u64(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u128(&mut self, i: u128) {
|
|
||||||
self.0.write_u128(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_usize(&mut self, i: usize) {
|
|
||||||
self.0.write_usize(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_i8(&mut self, i: i8) {
|
|
||||||
self.0.write_i8(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_i16(&mut self, i: i16) {
|
|
||||||
self.0.write_i16(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_i32(&mut self, i: i32) {
|
|
||||||
self.0.write_i32(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_i64(&mut self, i: i64) {
|
|
||||||
self.0.write_i64(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_i128(&mut self, i: i128) {
|
|
||||||
self.0.write_i128(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_isize(&mut self, i: isize) {
|
|
||||||
self.0.write_isize(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
||||||
// See Notices.txt for copyright information
|
|
||||||
|
|
||||||
//! check that SimValue can't be interned, since equality may ignore types
|
|
||||||
|
|
||||||
use fayalite::{
|
|
||||||
intern::{Intern, Interned},
|
|
||||||
sim::value::SimValue,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn f(v: SimValue<()>) -> Interned<SimValue<()>> {
|
|
||||||
Intern::intern_sized(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
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 `SimValue<()>`, the trait `Sync` is not implemented for `Cell<util::alternating_cell::State>`, which is required by `SimValue<()>: Sync`
|
|
||||||
= 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
|
|
||||||
|
|
|
||||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required because it appears within the type `SimValue<()>`
|
|
||||||
--> 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`
|
|
||||||
|
|
||||||
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 `SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell<value::SimValueInner<()>>`, which is required by `SimValue<()>: Sync`
|
|
||||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
|
||||||
--> src/util/alternating_cell.rs
|
|
||||||
|
|
|
||||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required because it appears within the type `SimValue<()>`
|
|
||||||
--> 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`
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `SimValue<()>: Intern` is not satisfied
|
|
||||||
--> tests/ui/simvalue_is_not_internable.rs:12:26
|
|
||||||
|
|
|
||||||
12 | Intern::intern_sized(v)
|
|
||||||
| -------------------- ^ the trait `Hash` is not implemented for `SimValue<()>`, which is required by `SimValue<()>: Intern`
|
|
||||||
| |
|
|
||||||
| required by a bound introduced by this call
|
|
||||||
|
|
|
||||||
= help: the following other types implement trait `Intern`:
|
|
||||||
BitSlice
|
|
||||||
[T]
|
|
||||||
str
|
|
||||||
= note: required for `SimValue<()>` to implement `Intern`
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `SimValue<()>: Intern` is not satisfied
|
|
||||||
--> tests/ui/simvalue_is_not_internable.rs:12:26
|
|
||||||
|
|
|
||||||
12 | Intern::intern_sized(v)
|
|
||||||
| -------------------- ^ the trait `std::cmp::Eq` is not implemented for `SimValue<()>`, which is required by `SimValue<()>: Intern`
|
|
||||||
| |
|
|
||||||
| required by a bound introduced by this call
|
|
||||||
|
|
|
||||||
= help: the following other types implement trait `Intern`:
|
|
||||||
BitSlice
|
|
||||||
[T]
|
|
||||||
str
|
|
||||||
= note: required for `SimValue<()>` to implement `Intern`
|
|
||||||
|
|
||||||
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 `SimValue<()>`, the trait `Sync` is not implemented for `Cell<util::alternating_cell::State>`, which is required by `SimValue<()>: Sync`
|
|
||||||
= 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
|
|
||||||
|
|
|
||||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required because it appears within the type `SimValue<()>`
|
|
||||||
--> 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`
|
|
||||||
| fn intern(&self) -> Interned<Self>;
|
|
||||||
| fn intern_sized(self) -> Interned<Self>
|
|
||||||
| ------------ required by a bound in this associated function
|
|
||||||
|
|
||||||
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 `SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell<value::SimValueInner<()>>`, which is required by `SimValue<()>: Sync`
|
|
||||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
|
||||||
--> src/util/alternating_cell.rs
|
|
||||||
|
|
|
||||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required because it appears within the type `SimValue<()>`
|
|
||||||
--> 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`
|
|
||||||
| fn intern(&self) -> Interned<Self>;
|
|
||||||
| fn intern_sized(self) -> Interned<Self>
|
|
||||||
| ------------ required by a bound in this associated function
|
|
||||||
|
|
||||||
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 `SimValue<()>`, the trait `Sync` is not implemented for `Cell<util::alternating_cell::State>`, which is required by `SimValue<()>: Sync`
|
|
||||||
= 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
|
|
||||||
|
|
|
||||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required because it appears within the type `SimValue<()>`
|
|
||||||
--> 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`
|
|
||||||
|
|
||||||
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 `SimValue<()>`, the trait `Sync` is not implemented for `UnsafeCell<value::SimValueInner<()>>`, which is required by `SimValue<()>: Sync`
|
|
||||||
note: required because it appears within the type `util::alternating_cell::AlternatingCell<value::SimValueInner<()>>`
|
|
||||||
--> src/util/alternating_cell.rs
|
|
||||||
|
|
|
||||||
| pub(crate) struct AlternatingCell<T: ?Sized> {
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
note: required because it appears within the type `SimValue<()>`
|
|
||||||
--> 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`
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue