forked from libre-chip/fayalite
		
	Compare commits
	
		
			10 commits
		
	
	
		
			36f1b9bbb6
			...
			668e714dc9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 668e714dc9 | |||
| 88323a8c16 | |||
| 91e1b619e8 | |||
| e2d2d4110b | |||
| b1f9706e4e | |||
| 4eda4366c8 | |||
| 122c08d3cf | |||
| b08a747e20 | |||
| e0c9939147 | |||
| 07725ab489 | 
					 23 changed files with 567 additions and 111 deletions
				
			
		| 
						 | 
				
			
			@ -59,3 +59,4 @@ jobs:
 | 
			
		|||
      - run: cargo build --tests --features=unstable-doc
 | 
			
		||||
      - run: cargo test --doc --features=unstable-doc
 | 
			
		||||
      - run: cargo doc --features=unstable-doc
 | 
			
		||||
      - run: FAYALITE_TEST_HASHER=always_zero cargo test --test=module --features=unstable-doc,unstable-test-hasher
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										56
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										56
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -2,18 +2,6 @@
 | 
			
		|||
# It is not intended for manual editing.
 | 
			
		||||
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]]
 | 
			
		||||
name = "allocator-api2"
 | 
			
		||||
version = "0.2.16"
 | 
			
		||||
| 
						 | 
				
			
			@ -365,6 +353,12 @@ version = "0.5.7"
 | 
			
		|||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "foldhash"
 | 
			
		||||
version = "0.1.5"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "funty"
 | 
			
		||||
version = "2.0.0"
 | 
			
		||||
| 
						 | 
				
			
			@ -400,12 +394,13 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 | 
			
		|||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "hashbrown"
 | 
			
		||||
version = "0.14.3"
 | 
			
		||||
version = "0.15.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
 | 
			
		||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "ahash",
 | 
			
		||||
 "allocator-api2",
 | 
			
		||||
 "equivalent",
 | 
			
		||||
 "foldhash",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
| 
						 | 
				
			
			@ -431,9 +426,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
 | 
			
		|||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "indexmap"
 | 
			
		||||
version = "2.5.0"
 | 
			
		||||
version = "2.9.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
 | 
			
		||||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "equivalent",
 | 
			
		||||
 "hashbrown",
 | 
			
		||||
| 
						 | 
				
			
			@ -524,11 +519,14 @@ dependencies = [
 | 
			
		|||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "petgraph"
 | 
			
		||||
version = "0.6.5"
 | 
			
		||||
source = "git+https://github.com/programmerjake/petgraph.git?rev=258ea8071209a924b73fe96f9f87a3b7b45cbc9f#258ea8071209a924b73fe96f9f87a3b7b45cbc9f"
 | 
			
		||||
version = "0.8.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7a98c6720655620a521dcc722d0ad66cd8afd5d86e34a89ef691c50b7b24de06"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "fixedbitset",
 | 
			
		||||
 "hashbrown",
 | 
			
		||||
 "indexmap",
 | 
			
		||||
 "serde",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
| 
						 | 
				
			
			@ -893,23 +891,3 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
 | 
			
		|||
dependencies = [
 | 
			
		||||
 "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,14 +23,13 @@ blake3 = { version = "1.5.4", features = ["serde"] }
 | 
			
		|||
clap = { version = "4.5.9", features = ["derive", "env", "string"] }
 | 
			
		||||
ctor = "0.2.8"
 | 
			
		||||
eyre = "0.6.12"
 | 
			
		||||
hashbrown = "0.14.3"
 | 
			
		||||
hashbrown = "0.15.2"
 | 
			
		||||
indexmap = { version = "2.5.0", features = ["serde"] }
 | 
			
		||||
jobslot = "0.2.19"
 | 
			
		||||
num-bigint = "0.4.6"
 | 
			
		||||
num-traits = "0.2.16"
 | 
			
		||||
os_pipe = "1.2.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" }
 | 
			
		||||
petgraph = "0.8.1"
 | 
			
		||||
prettyplease = "0.2.20"
 | 
			
		||||
proc-macro2 = "1.0.83"
 | 
			
		||||
quote = "1.0.36"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,6 +40,7 @@ fayalite-visit-gen.workspace = true
 | 
			
		|||
 | 
			
		||||
[features]
 | 
			
		||||
unstable-doc = []
 | 
			
		||||
unstable-test-hasher = []
 | 
			
		||||
 | 
			
		||||
[package.metadata.docs.rs]
 | 
			
		||||
features = ["unstable-doc"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,9 +14,9 @@ use crate::{
 | 
			
		|||
        impl_match_variant_as_self, CanonicalType, MatchVariantWithoutScope, OpaqueSimValue,
 | 
			
		||||
        StaticType, Type, TypeProperties, TypeWithDeref,
 | 
			
		||||
    },
 | 
			
		||||
    util::HashMap,
 | 
			
		||||
};
 | 
			
		||||
use bitvec::{slice::BitSlice, vec::BitVec};
 | 
			
		||||
use hashbrown::HashMap;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use std::{fmt, marker::PhantomData};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +160,7 @@ impl Default for BundleTypePropertiesBuilder {
 | 
			
		|||
impl Bundle {
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    pub fn new(fields: Interned<[BundleField]>) -> Self {
 | 
			
		||||
        let mut name_indexes = HashMap::with_capacity(fields.len());
 | 
			
		||||
        let mut name_indexes = HashMap::with_capacity_and_hasher(fields.len(), Default::default());
 | 
			
		||||
        let mut field_offsets = Vec::with_capacity(fields.len());
 | 
			
		||||
        let mut type_props_builder = BundleTypePropertiesBuilder::new();
 | 
			
		||||
        for (index, &BundleField { name, flipped, ty }) in fields.iter().enumerate() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -258,7 +258,7 @@ pub struct VerilogArgs {
 | 
			
		|||
        default_value = "firtool",
 | 
			
		||||
        env = "FIRTOOL",
 | 
			
		||||
        value_hint = ValueHint::CommandName,
 | 
			
		||||
        value_parser = OsStringValueParser::new().try_map(which::which)
 | 
			
		||||
        value_parser = OsStringValueParser::new().try_map(which)
 | 
			
		||||
    )]
 | 
			
		||||
    pub firtool: PathBuf,
 | 
			
		||||
    #[arg(long)]
 | 
			
		||||
| 
						 | 
				
			
			@ -428,6 +428,13 @@ 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)]
 | 
			
		||||
#[non_exhaustive]
 | 
			
		||||
pub struct FormalArgs {
 | 
			
		||||
| 
						 | 
				
			
			@ -438,7 +445,7 @@ pub struct FormalArgs {
 | 
			
		|||
        default_value = "sby",
 | 
			
		||||
        env = "SBY",
 | 
			
		||||
        value_hint = ValueHint::CommandName,
 | 
			
		||||
        value_parser = OsStringValueParser::new().try_map(which::which)
 | 
			
		||||
        value_parser = OsStringValueParser::new().try_map(which)
 | 
			
		||||
    )]
 | 
			
		||||
    pub sby: PathBuf,
 | 
			
		||||
    #[arg(long)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,9 @@ use crate::{
 | 
			
		|||
        CanonicalType, MatchVariantAndInactiveScope, OpaqueSimValue, StaticType, Type,
 | 
			
		||||
        TypeProperties,
 | 
			
		||||
    },
 | 
			
		||||
    util::HashMap,
 | 
			
		||||
};
 | 
			
		||||
use bitvec::{order::Lsb0, slice::BitSlice, view::BitView};
 | 
			
		||||
use hashbrown::HashMap;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use std::{convert::Infallible, fmt, iter::FusedIterator, sync::Arc};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +193,8 @@ impl Default for EnumTypePropertiesBuilder {
 | 
			
		|||
impl Enum {
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    pub fn new(variants: Interned<[EnumVariant]>) -> Self {
 | 
			
		||||
        let mut name_indexes = HashMap::with_capacity(variants.len());
 | 
			
		||||
        let mut name_indexes =
 | 
			
		||||
            HashMap::with_capacity_and_hasher(variants.len(), Default::default());
 | 
			
		||||
        let mut type_props_builder = EnumTypePropertiesBuilder::new();
 | 
			
		||||
        for (index, EnumVariant { name, ty }) in variants.iter().enumerate() {
 | 
			
		||||
            if let Some(old_index) = name_indexes.insert(*name, index) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -274,6 +274,17 @@ pub struct Expr<T: Type> {
 | 
			
		|||
 | 
			
		||||
impl<T: Type + fmt::Debug> fmt::Debug for Expr<T> {
 | 
			
		||||
    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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,12 +36,11 @@ use crate::{
 | 
			
		|||
    ty::{CanonicalType, Type},
 | 
			
		||||
    util::{
 | 
			
		||||
        const_str_array_is_strictly_ascending, BitSliceWriteWithBase, DebugAsRawString,
 | 
			
		||||
        GenericConstBool,
 | 
			
		||||
        GenericConstBool, HashMap, HashSet,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
use bitvec::slice::BitSlice;
 | 
			
		||||
use clap::value_parser;
 | 
			
		||||
use hashbrown::{HashMap, HashSet};
 | 
			
		||||
use num_traits::Signed;
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
use std::{
 | 
			
		||||
| 
						 | 
				
			
			@ -2622,7 +2621,7 @@ fn export_impl(
 | 
			
		|||
            indent_depth: &indent_depth,
 | 
			
		||||
            indent: "    ",
 | 
			
		||||
        },
 | 
			
		||||
        seen_modules: HashSet::new(),
 | 
			
		||||
        seen_modules: HashSet::default(),
 | 
			
		||||
        unwritten_modules: VecDeque::new(),
 | 
			
		||||
        global_ns,
 | 
			
		||||
        module: ModuleState::default(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
			
		||||
// See Notices.txt for copyright information
 | 
			
		||||
#![allow(clippy::type_complexity)]
 | 
			
		||||
use crate::intern::type_map::TypeIdMap;
 | 
			
		||||
use crate::{intern::type_map::TypeIdMap, util::DefaultBuildHasher};
 | 
			
		||||
use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec};
 | 
			
		||||
use hashbrown::{hash_map::RawEntryMut, HashMap, HashTable};
 | 
			
		||||
use hashbrown::HashTable;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use std::{
 | 
			
		||||
    any::{Any, TypeId},
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ use std::{
 | 
			
		|||
    sync::{Mutex, RwLock},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
pub mod type_map;
 | 
			
		||||
mod type_map;
 | 
			
		||||
 | 
			
		||||
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
 | 
			
		||||
    fn get(&self) -> Interned<T>;
 | 
			
		||||
| 
						 | 
				
			
			@ -316,8 +316,13 @@ 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> {
 | 
			
		||||
    map: Mutex<HashMap<&'static T, ()>>,
 | 
			
		||||
    state: Mutex<InternerState<T>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
 | 
			
		||||
| 
						 | 
				
			
			@ -330,7 +335,10 @@ impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
 | 
			
		|||
impl<T: ?Sized + 'static + Send + Sync> Default for Interner<T> {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            map: Default::default(),
 | 
			
		||||
            state: Mutex::new(InternerState {
 | 
			
		||||
                table: HashTable::new(),
 | 
			
		||||
                hasher: Default::default(),
 | 
			
		||||
            }),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -341,17 +349,16 @@ impl<T: ?Sized + 'static + Send + Sync + Hash + Eq + ToOwned> Interner<T> {
 | 
			
		|||
        alloc: F,
 | 
			
		||||
        value: Cow<'_, T>,
 | 
			
		||||
    ) -> Interned<T> {
 | 
			
		||||
        let mut map = self.map.lock().unwrap();
 | 
			
		||||
        let hasher = map.hasher().clone();
 | 
			
		||||
        let hash = hasher.hash_one(&*value);
 | 
			
		||||
        let inner = match map.raw_entry_mut().from_hash(hash, |k| **k == *value) {
 | 
			
		||||
            RawEntryMut::Occupied(entry) => *entry.key(),
 | 
			
		||||
            RawEntryMut::Vacant(entry) => {
 | 
			
		||||
                *entry
 | 
			
		||||
                    .insert_with_hasher(hash, alloc(value), (), |k| hasher.hash_one(&**k))
 | 
			
		||||
                    .0
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        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 }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -742,7 +749,7 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy {
 | 
			
		|||
    fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
 | 
			
		||||
        static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
 | 
			
		||||
        let map: &RwLock<(
 | 
			
		||||
            hashbrown::hash_map::DefaultHashBuilder,
 | 
			
		||||
            DefaultBuildHasher,
 | 
			
		||||
            HashTable<(Self, Self::InputOwned, Self::Output)>,
 | 
			
		||||
        )> = TYPE_ID_MAP.get_or_insert_default();
 | 
			
		||||
        fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,10 +24,10 @@ use crate::{
 | 
			
		|||
    sim::{ExternModuleSimGenerator, ExternModuleSimulation},
 | 
			
		||||
    source_location::SourceLocation,
 | 
			
		||||
    ty::{CanonicalType, Type},
 | 
			
		||||
    util::ScopedRef,
 | 
			
		||||
    util::{HashMap, HashSet, ScopedRef},
 | 
			
		||||
    wire::{IncompleteWire, Wire},
 | 
			
		||||
};
 | 
			
		||||
use hashbrown::{hash_map::Entry, HashMap, HashSet};
 | 
			
		||||
use hashbrown::hash_map::Entry;
 | 
			
		||||
use num_bigint::BigInt;
 | 
			
		||||
use std::{
 | 
			
		||||
    cell::RefCell,
 | 
			
		||||
| 
						 | 
				
			
			@ -1498,7 +1498,7 @@ impl TargetState {
 | 
			
		|||
                        .collect(),
 | 
			
		||||
                },
 | 
			
		||||
                CanonicalType::PhantomConst(_) => TargetStateInner::Decomposed {
 | 
			
		||||
                    subtargets: HashMap::new(),
 | 
			
		||||
                    subtargets: HashMap::default(),
 | 
			
		||||
                },
 | 
			
		||||
                CanonicalType::Array(ty) => TargetStateInner::Decomposed {
 | 
			
		||||
                    subtargets: (0..ty.len())
 | 
			
		||||
| 
						 | 
				
			
			@ -1864,7 +1864,7 @@ impl<T: BundleType> Module<T> {
 | 
			
		|||
        AssertValidityState {
 | 
			
		||||
            module: self.canonical(),
 | 
			
		||||
            blocks: vec![],
 | 
			
		||||
            target_states: HashMap::with_capacity(64),
 | 
			
		||||
            target_states: HashMap::with_capacity_and_hasher(64, Default::default()),
 | 
			
		||||
        }
 | 
			
		||||
        .assert_validity();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2125,8 +2125,8 @@ impl ModuleBuilder {
 | 
			
		|||
                        incomplete_declarations: vec![],
 | 
			
		||||
                        stmts: vec![],
 | 
			
		||||
                    }],
 | 
			
		||||
                    annotations_map: HashMap::new(),
 | 
			
		||||
                    memory_map: HashMap::new(),
 | 
			
		||||
                    annotations_map: HashMap::default(),
 | 
			
		||||
                    memory_map: HashMap::default(),
 | 
			
		||||
                },
 | 
			
		||||
            }),
 | 
			
		||||
        };
 | 
			
		||||
| 
						 | 
				
			
			@ -2136,7 +2136,7 @@ impl ModuleBuilder {
 | 
			
		|||
            impl_: RefCell::new(ModuleBuilderImpl {
 | 
			
		||||
                body,
 | 
			
		||||
                io: vec![],
 | 
			
		||||
                io_indexes: HashMap::new(),
 | 
			
		||||
                io_indexes: HashMap::default(),
 | 
			
		||||
                module_annotations: vec![],
 | 
			
		||||
            }),
 | 
			
		||||
        };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,9 @@ use crate::{
 | 
			
		|||
    },
 | 
			
		||||
    prelude::*,
 | 
			
		||||
    reset::{ResetType, ResetTypeDispatch},
 | 
			
		||||
    util::{HashMap, HashSet},
 | 
			
		||||
};
 | 
			
		||||
use hashbrown::{hash_map::Entry, HashMap, HashSet};
 | 
			
		||||
use hashbrown::hash_map::Entry;
 | 
			
		||||
use num_bigint::BigInt;
 | 
			
		||||
use petgraph::unionfind::UnionFind;
 | 
			
		||||
use std::{fmt, marker::PhantomData};
 | 
			
		||||
| 
						 | 
				
			
			@ -2251,9 +2252,9 @@ pub fn deduce_resets(
 | 
			
		|||
    fallback_to_sync_reset: bool,
 | 
			
		||||
) -> Result<Interned<Module<Bundle>>, DeduceResetsError> {
 | 
			
		||||
    let mut state = State {
 | 
			
		||||
        modules_added_to_graph: HashSet::new(),
 | 
			
		||||
        substituted_modules: HashMap::new(),
 | 
			
		||||
        expr_resets: HashMap::new(),
 | 
			
		||||
        modules_added_to_graph: HashSet::default(),
 | 
			
		||||
        substituted_modules: HashMap::default(),
 | 
			
		||||
        expr_resets: HashMap::default(),
 | 
			
		||||
        reset_graph: ResetGraph::default(),
 | 
			
		||||
        fallback_to_sync_reset,
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,10 +18,10 @@ use crate::{
 | 
			
		|||
    },
 | 
			
		||||
    source_location::SourceLocation,
 | 
			
		||||
    ty::{CanonicalType, Type},
 | 
			
		||||
    util::HashMap,
 | 
			
		||||
    wire::Wire,
 | 
			
		||||
};
 | 
			
		||||
use core::fmt;
 | 
			
		||||
use hashbrown::HashMap;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum SimplifyEnumsError {
 | 
			
		||||
| 
						 | 
				
			
			@ -965,8 +965,8 @@ pub fn simplify_enums(
 | 
			
		|||
    kind: SimplifyEnumsKind,
 | 
			
		||||
) -> Result<Interned<Module<Bundle>>, SimplifyEnumsError> {
 | 
			
		||||
    module.fold(&mut State {
 | 
			
		||||
        enum_types: HashMap::new(),
 | 
			
		||||
        replacement_mem_ports: HashMap::new(),
 | 
			
		||||
        enum_types: HashMap::default(),
 | 
			
		||||
        replacement_mem_ports: HashMap::default(),
 | 
			
		||||
        kind,
 | 
			
		||||
        module_state_stack: vec![],
 | 
			
		||||
    })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,11 +14,10 @@ use crate::{
 | 
			
		|||
    },
 | 
			
		||||
    source_location::SourceLocation,
 | 
			
		||||
    ty::{CanonicalType, Type},
 | 
			
		||||
    util::MakeMutSlice,
 | 
			
		||||
    util::{HashMap, MakeMutSlice},
 | 
			
		||||
    wire::Wire,
 | 
			
		||||
};
 | 
			
		||||
use bitvec::{slice::BitSlice, vec::BitVec};
 | 
			
		||||
use hashbrown::HashMap;
 | 
			
		||||
use std::{
 | 
			
		||||
    convert::Infallible,
 | 
			
		||||
    fmt::Write,
 | 
			
		||||
| 
						 | 
				
			
			@ -897,7 +896,7 @@ impl Folder for State {
 | 
			
		|||
            module,
 | 
			
		||||
            ModuleState {
 | 
			
		||||
                output_module: None,
 | 
			
		||||
                memories: HashMap::new(),
 | 
			
		||||
                memories: HashMap::default(),
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
        let mut this = PushedState::push_module(self, module);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,10 +41,9 @@ use crate::{
 | 
			
		|||
        value::SimValue,
 | 
			
		||||
    },
 | 
			
		||||
    ty::StaticType,
 | 
			
		||||
    util::{BitSliceWriteWithBase, DebugAsDisplay},
 | 
			
		||||
    util::{BitSliceWriteWithBase, DebugAsDisplay, HashMap, HashSet},
 | 
			
		||||
};
 | 
			
		||||
use bitvec::{bits, order::Lsb0, slice::BitSlice, vec::BitVec, view::BitView};
 | 
			
		||||
use hashbrown::{HashMap, HashSet};
 | 
			
		||||
use num_bigint::BigInt;
 | 
			
		||||
use num_traits::{Signed, Zero};
 | 
			
		||||
use petgraph::{
 | 
			
		||||
| 
						 | 
				
			
			@ -580,8 +579,9 @@ impl Assignments {
 | 
			
		|||
            big_slots,
 | 
			
		||||
        }) = self.slot_readers();
 | 
			
		||||
        AssignmentsElements {
 | 
			
		||||
            node_indexes: HashMap::with_capacity(
 | 
			
		||||
            node_indexes: HashMap::with_capacity_and_hasher(
 | 
			
		||||
                self.assignments().len() + small_slots.len() + big_slots.len(),
 | 
			
		||||
                Default::default(),
 | 
			
		||||
            ),
 | 
			
		||||
            nodes: self.node_references(),
 | 
			
		||||
            edges: self.edge_references(),
 | 
			
		||||
| 
						 | 
				
			
			@ -1022,6 +1022,16 @@ impl VisitMap<AssignmentOrSlotIndex> for AssignmentsVisitMap {
 | 
			
		|||
            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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -1676,18 +1686,18 @@ impl Compiler {
 | 
			
		|||
            insns: Insns::new(),
 | 
			
		||||
            original_base_module,
 | 
			
		||||
            base_module,
 | 
			
		||||
            modules: HashMap::new(),
 | 
			
		||||
            modules: HashMap::default(),
 | 
			
		||||
            extern_modules: Vec::new(),
 | 
			
		||||
            compiled_values: HashMap::new(),
 | 
			
		||||
            compiled_exprs: HashMap::new(),
 | 
			
		||||
            compiled_exprs_to_values: HashMap::new(),
 | 
			
		||||
            decl_conditions: HashMap::new(),
 | 
			
		||||
            compiled_values_to_dyn_array_indexes: HashMap::new(),
 | 
			
		||||
            compiled_value_bool_dest_is_small_map: HashMap::new(),
 | 
			
		||||
            compiled_values: HashMap::default(),
 | 
			
		||||
            compiled_exprs: HashMap::default(),
 | 
			
		||||
            compiled_exprs_to_values: HashMap::default(),
 | 
			
		||||
            decl_conditions: HashMap::default(),
 | 
			
		||||
            compiled_values_to_dyn_array_indexes: HashMap::default(),
 | 
			
		||||
            compiled_value_bool_dest_is_small_map: HashMap::default(),
 | 
			
		||||
            assignments: Assignments::default(),
 | 
			
		||||
            clock_triggers: Vec::new(),
 | 
			
		||||
            compiled_value_to_clock_trigger_map: HashMap::new(),
 | 
			
		||||
            enum_discriminants: HashMap::new(),
 | 
			
		||||
            compiled_value_to_clock_trigger_map: HashMap::default(),
 | 
			
		||||
            enum_discriminants: HashMap::default(),
 | 
			
		||||
            registers: Vec::new(),
 | 
			
		||||
            traces: SimTraces(Vec::new()),
 | 
			
		||||
            memories: Vec::new(),
 | 
			
		||||
| 
						 | 
				
			
			@ -5976,8 +5986,8 @@ impl SimulationModuleState {
 | 
			
		|||
    fn new(base_targets: impl IntoIterator<Item = (Target, CompiledValue<CanonicalType>)>) -> Self {
 | 
			
		||||
        let mut retval = Self {
 | 
			
		||||
            base_targets: Vec::new(),
 | 
			
		||||
            uninitialized_ios: HashMap::new(),
 | 
			
		||||
            io_targets: HashMap::new(),
 | 
			
		||||
            uninitialized_ios: HashMap::default(),
 | 
			
		||||
            io_targets: HashMap::default(),
 | 
			
		||||
            did_initial_settle: false,
 | 
			
		||||
        };
 | 
			
		||||
        for (base_target, value) in base_targets {
 | 
			
		||||
| 
						 | 
				
			
			@ -6207,7 +6217,7 @@ impl Default for EarliestWaitTargets {
 | 
			
		|||
        Self {
 | 
			
		||||
            settle: false,
 | 
			
		||||
            instant: None,
 | 
			
		||||
            changes: HashMap::new(),
 | 
			
		||||
            changes: HashMap::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6217,14 +6227,14 @@ impl EarliestWaitTargets {
 | 
			
		|||
        Self {
 | 
			
		||||
            settle: true,
 | 
			
		||||
            instant: None,
 | 
			
		||||
            changes: HashMap::new(),
 | 
			
		||||
            changes: HashMap::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    fn instant(instant: SimInstant) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            settle: false,
 | 
			
		||||
            instant: Some(instant),
 | 
			
		||||
            changes: HashMap::new(),
 | 
			
		||||
            changes: HashMap::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    fn len(&self) -> usize {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,10 +7,9 @@ use crate::{
 | 
			
		|||
    intern::{Intern, Interned, Memoize},
 | 
			
		||||
    source_location::SourceLocation,
 | 
			
		||||
    ty::CanonicalType,
 | 
			
		||||
    util::get_many_mut,
 | 
			
		||||
    util::{get_many_mut, HashMap, HashSet},
 | 
			
		||||
};
 | 
			
		||||
use bitvec::{boxed::BitBox, slice::BitSlice};
 | 
			
		||||
use hashbrown::{HashMap, HashSet};
 | 
			
		||||
use num_bigint::BigInt;
 | 
			
		||||
use num_traits::{One, Signed, ToPrimitive, Zero};
 | 
			
		||||
use std::{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,9 +14,10 @@ use crate::{
 | 
			
		|||
        TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId, TraceScope, TraceSyncReset,
 | 
			
		||||
        TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
 | 
			
		||||
    },
 | 
			
		||||
    util::HashMap,
 | 
			
		||||
};
 | 
			
		||||
use bitvec::{order::Lsb0, slice::BitSlice};
 | 
			
		||||
use hashbrown::{hash_map::Entry, HashMap};
 | 
			
		||||
use hashbrown::hash_map::Entry;
 | 
			
		||||
use std::{
 | 
			
		||||
    fmt::{self, Write as _},
 | 
			
		||||
    io, mem,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,9 +2,8 @@
 | 
			
		|||
// See Notices.txt for copyright information
 | 
			
		||||
use crate::{
 | 
			
		||||
    intern::{Intern, Interned},
 | 
			
		||||
    util::DebugAsDisplay,
 | 
			
		||||
    util::{DebugAsDisplay, HashMap},
 | 
			
		||||
};
 | 
			
		||||
use hashbrown::HashMap;
 | 
			
		||||
use std::{cell::RefCell, fmt, num::NonZeroUsize, panic, path::Path};
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 | 
			
		||||
| 
						 | 
				
			
			@ -97,7 +96,7 @@ impl NormalizeFilesForTestsState {
 | 
			
		|||
    fn new() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            test_position: panic::Location::caller(),
 | 
			
		||||
            file_pattern_matches: HashMap::new(),
 | 
			
		||||
            file_pattern_matches: HashMap::default(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +142,7 @@ impl From<&'_ panic::Location<'_>> for SourceLocation {
 | 
			
		|||
                        map.entry_ref(file)
 | 
			
		||||
                            .or_insert_with(|| NormalizedFileForTestState {
 | 
			
		||||
                                file_name_id: NonZeroUsize::new(len + 1).unwrap(),
 | 
			
		||||
                                positions_map: HashMap::new(),
 | 
			
		||||
                                positions_map: HashMap::default(),
 | 
			
		||||
                            });
 | 
			
		||||
                    file_str = m.generate_file_name(file_state.file_name_id);
 | 
			
		||||
                    file = &file_str;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,9 @@
 | 
			
		|||
use crate::{
 | 
			
		||||
    cli::{FormalArgs, FormalMode, FormalOutput, RunPhase},
 | 
			
		||||
    firrtl::ExportOptions,
 | 
			
		||||
    util::HashMap,
 | 
			
		||||
};
 | 
			
		||||
use clap::Parser;
 | 
			
		||||
use hashbrown::HashMap;
 | 
			
		||||
use serde::Deserialize;
 | 
			
		||||
use std::{
 | 
			
		||||
    fmt::Write,
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ fn get_assert_formal_target_path(test_name: &dyn std::fmt::Display) -> PathBuf {
 | 
			
		|||
    let index = *DIRS
 | 
			
		||||
        .lock()
 | 
			
		||||
        .unwrap()
 | 
			
		||||
        .get_or_insert_with(HashMap::new)
 | 
			
		||||
        .get_or_insert_with(HashMap::default)
 | 
			
		||||
        .entry_ref(&dir)
 | 
			
		||||
        .and_modify(|v| *v += 1)
 | 
			
		||||
        .or_insert(0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,16 @@ mod const_usize;
 | 
			
		|||
mod misc;
 | 
			
		||||
mod scoped_ref;
 | 
			
		||||
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)]
 | 
			
		||||
pub use const_bool::{ConstBool, ConstBoolDispatch, ConstBoolDispatchTag, GenericConstBool};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										240
									
								
								crates/fayalite/src/util/test_hasher.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								crates/fayalite/src/util/test_hasher.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,240 @@
 | 
			
		|||
// 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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								crates/fayalite/tests/ui/simvalue_is_not_internable.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								crates/fayalite/tests/ui/simvalue_is_not_internable.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
// 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() {}
 | 
			
		||||
							
								
								
									
										178
									
								
								crates/fayalite/tests/ui/simvalue_is_not_internable.stderr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								crates/fayalite/tests/ui/simvalue_is_not_internable.stderr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,178 @@
 | 
			
		|||
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