diff --git a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs index cf08c7e..f3a589a 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_bundle.rs @@ -58,7 +58,8 @@ impl ParsedBundle { } *mutability = FieldMutability::None; colon_token.get_or_insert(Token![:](ident.span())); - errors.unwrap_or_default(HdlAttr::parse_and_take_attr(attrs)) + let options = errors.unwrap_or_default(HdlAttr::parse_and_take_attr(attrs)); + options } fn parse(item: ItemStruct) -> syn::Result { let ItemStruct { @@ -685,7 +686,7 @@ impl ToTokens for ParsedBundle { let __retval = #mask_type_match_variant_ident { #(#match_variant_body_fields)* }; - ::fayalite::intern::Interned::into_inner(::fayalite::intern::Intern::intern_sized(__retval)) + ::fayalite::intern::Interned::<_>::into_inner(::fayalite::intern::Intern::intern_sized(__retval)) } } #[automatically_derived] @@ -760,7 +761,7 @@ impl ToTokens for ParsedBundle { let __retval = #match_variant_ident { #(#match_variant_body_fields)* }; - ::fayalite::intern::Interned::into_inner(::fayalite::intern::Intern::intern_sized(__retval)) + ::fayalite::intern::Interned::<_>::into_inner(::fayalite::intern::Intern::intern_sized(__retval)) } } } diff --git a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs index 1d16177..adddd74 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_enum.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_enum.rs @@ -600,7 +600,7 @@ impl ToTokens for ParsedEnum { static_generics.split_for_impl(); let static_type_body_variants = Vec::from_iter(variants.iter().map(|ParsedVariant { ident, field, .. }| { - if field.is_some() { + if let Some(_) = field { quote_spanned! {span=> #ident: ::fayalite::ty::StaticType::TYPE, } diff --git a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs index e36f68e..e7561fe 100644 --- a/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs +++ b/crates/fayalite-proc-macros-impl/src/hdl_type_common.rs @@ -1410,7 +1410,7 @@ impl ParseTypes for ParsedType { let mut args = None; let segments = Punctuated::from_iter(segments.pairs_mut().map_pair_value_mut(|segment| { let PathSegment { ident, arguments } = segment; - if args.is_some() { + if let Some(_) = args { parser .errors() .error(&ident, "associated types/consts are not yet implemented"); @@ -1594,7 +1594,7 @@ impl ParseTypes for ParsedConstGenericType { let mut args = None; let segments = Punctuated::from_iter(segments.pairs_mut().map_pair_value_mut(|segment| { let PathSegment { ident, arguments } = segment; - if args.is_some() { + if let Some(_) = args { parser .errors() .error(&ident, "associated types/consts are not yet implemented"); @@ -2718,7 +2718,7 @@ impl ParsedGenerics { type Output = #next_target #next_type_generics; fn index(&self, #param_token: #index_type) -> &Self::Output { - ::fayalite::intern::Interned::into_inner( + ::fayalite::intern::Interned::<_>::into_inner( ::fayalite::intern::Intern::intern_sized(#output_expr), ) } @@ -2778,7 +2778,7 @@ impl ParsedGenerics { type Output = #next_target #next_target_args; fn index(&self, #param_token: #param_ident) -> &Self::Output { - ::fayalite::intern::Interned::into_inner( + ::fayalite::intern::Interned::<_>::into_inner( ::fayalite::intern::Intern::intern_sized(#output_expr), ) } @@ -2848,7 +2848,7 @@ impl ParsedGenerics { type Output = #next_target #next_target_args; fn index(&self, #param_token: __Param) -> &Self::Output { - ::fayalite::intern::Interned::into_inner( + ::fayalite::intern::Interned::<_>::into_inner( ::fayalite::intern::Intern::intern_sized(#output_expr), ) } @@ -3554,7 +3554,7 @@ impl SplitForImpl for Generics { Self::TypeGenerics<'_>, Self::WhereClause<'_>, ) { - Generics::split_for_impl(self) + Generics::split_for_impl(&self) } } diff --git a/crates/fayalite/src/array.rs b/crates/fayalite/src/array.rs index a3aea79..d543322 100644 --- a/crates/fayalite/src/array.rs +++ b/crates/fayalite/src/array.rs @@ -187,7 +187,7 @@ impl TypeWithDeref for ArrayType { let base = Expr::as_dyn_array(*this); let base_ty = Expr::ty(base); let retval = Vec::from_iter((0..base_ty.len()).map(|i| ArrayIndex::new(base, i).to_expr())); - Interned::into_inner(Intern::intern_sized( + Interned::<_>::into_inner(Intern::intern_sized( Len::ArrayMatch::::try_from(retval) .ok() .expect("unreachable"), @@ -202,7 +202,7 @@ impl Index for ArrayWithoutGenerics { type Output = ArrayWithoutLen; fn index(&self, element: T) -> &Self::Output { - Interned::into_inner(Intern::intern_sized(ArrayWithoutLen { element })) + Interned::<_>::into_inner(Intern::intern_sized(ArrayWithoutLen { element })) } } @@ -215,6 +215,6 @@ impl Index for ArrayWithoutLen { type Output = ArrayType; fn index(&self, len: L) -> &Self::Output { - Interned::into_inner(Intern::intern_sized(ArrayType::new(self.element, len))) + Interned::<_>::into_inner(Intern::intern_sized(ArrayType::new(self.element, len))) } } diff --git a/crates/fayalite/src/bundle.rs b/crates/fayalite/src/bundle.rs index b338322..95c87f9 100644 --- a/crates/fayalite/src/bundle.rs +++ b/crates/fayalite/src/bundle.rs @@ -144,12 +144,6 @@ impl BundleTypePropertiesBuilder { } } -impl Default for BundleTypePropertiesBuilder { - fn default() -> Self { - Self::new() - } -} - impl Bundle { #[track_caller] pub fn new(fields: Interned<[BundleField]>) -> Self { @@ -348,7 +342,6 @@ macro_rules! impl_tuples { std::iter::once(MatchVariantWithoutScope(($(Expr::field(this, stringify!($num)),)*))) } fn mask_type(&self) -> Self::MaskType { - #![allow(clippy::unused_unit)] let ($($var,)*) = self; ($($var.mask_type(),)*) } @@ -357,7 +350,6 @@ macro_rules! impl_tuples { } #[track_caller] fn from_canonical(canonical_type: CanonicalType) -> Self { - #![allow(clippy::unused_unit)] let CanonicalType::Bundle(bundle) = canonical_type else { panic!("expected bundle"); }; @@ -366,7 +358,7 @@ macro_rules! impl_tuples { }; $(let BundleField { name, flipped, ty } = $var; assert_eq!(&*name, stringify!($num)); - assert!(!flipped); + assert_eq!(flipped, false); let $var = $T::from_canonical(ty);)* ($($var,)*) } @@ -385,7 +377,7 @@ macro_rules! impl_tuples { impl<$($T: Type,)*> TypeWithDeref for ($($T,)*) { fn expr_deref(this: &Expr) -> &Self::MatchVariant { let _ = this; - Interned::into_inner(($(Expr::field(*this, stringify!($num)),)*).intern_sized()) + Interned::<_>::into_inner(($(Expr::field(*this, stringify!($num)),)*).intern_sized()) } } impl<$($T: StaticType,)*> StaticType for ($($T,)*) { diff --git a/crates/fayalite/src/enum_.rs b/crates/fayalite/src/enum_.rs index 2ed0b8e..13724ef 100644 --- a/crates/fayalite/src/enum_.rs +++ b/crates/fayalite/src/enum_.rs @@ -169,12 +169,6 @@ impl EnumTypePropertiesBuilder { } } -impl Default for EnumTypePropertiesBuilder { - fn default() -> Self { - Self::new() - } -} - impl Enum { #[track_caller] pub fn new(variants: Interned<[EnumVariant]>) -> Self { @@ -405,8 +399,9 @@ impl HdlOption { else { unreachable!(); }; - let value = f(value).inspect_err(|_| { + let value = f(value).map_err(|e| { and_then_out.complete(()); // avoid error + e })?; let and_then_out = and_then_out.complete(Expr::ty(value)); connect(and_then_out, value); diff --git a/crates/fayalite/src/expr/ops.rs b/crates/fayalite/src/expr/ops.rs index 3579641..6069f20 100644 --- a/crates/fayalite/src/expr/ops.rs +++ b/crates/fayalite/src/expr/ops.rs @@ -2057,7 +2057,7 @@ impl ExprIndex for ArrayType, index: usize) -> &Expr { - Interned::into_inner( + Interned::<_>::into_inner( ArrayIndex::::new(Expr::as_dyn_array(*this), index) .to_expr() .intern_sized(), @@ -2154,7 +2154,7 @@ impl ExprIndex>> type Output = ElementType; fn expr_index(this: &Expr, index: Expr>) -> &Expr { - Interned::into_inner( + Interned::<_>::into_inner( DynArrayIndex::::new(Expr::as_dyn_array(*this), Expr::as_dyn_int(index)) .to_expr() .intern_sized(), @@ -2279,7 +2279,7 @@ macro_rules! impl_int_slice { let base = Expr::as_dyn_int(*this); let base_ty = Expr::ty(base); let range = base_ty.slice_index_to_range(index); - Interned::into_inner($name::new(base, range).to_expr().intern_sized()) + Interned::<_>::into_inner($name::new(base, range).to_expr().intern_sized()) } } @@ -2291,7 +2291,7 @@ macro_rules! impl_int_slice { let base = Expr::as_dyn_int(*this); let base_ty = Expr::ty(base); assert!(index < base_ty.width()); - Interned::into_inner( + Interned::<_>::into_inner( $name::new(base, index..(index + 1)) .to_expr() .cast_to_static::() diff --git a/crates/fayalite/src/int.rs b/crates/fayalite/src/int.rs index dd631d0..e0d258a 100644 --- a/crates/fayalite/src/int.rs +++ b/crates/fayalite/src/int.rs @@ -147,7 +147,7 @@ where fn try_from_usize(v: usize) -> Option { if v == VALUE { - Some(ConstUsize) + Some(Self::SizeType::default()) } else { None } @@ -301,7 +301,7 @@ macro_rules! impl_int { type Output = $name; fn index(&self, width: Width) -> &Self::Output { - Interned::into_inner(Intern::intern_sized($name::new(width))) + Interned::<_>::into_inner(Intern::intern_sized($name::new(width))) } } @@ -560,7 +560,7 @@ pub trait BoolOrIntType: Type + sealed::BoolOrIntTypeSealed { } fn bits_to_expr(bits: Cow<'_, BitSlice>) -> Expr; fn le_bytes_to_expr_wrapping(bytes: &[u8], bit_width: usize) -> Expr { - let bitslice = BitSlice::::from_slice(bytes); + let bitslice = BitSlice::::from_slice(&bytes); let bitslice = &bitslice[..bit_width.min(bitslice.len())]; let mut bits = BitVec::new(); bits.extend_from_bitslice(bitslice); diff --git a/crates/fayalite/src/intern.rs b/crates/fayalite/src/intern.rs index 3780ad3..9bd4d56 100644 --- a/crates/fayalite/src/intern.rs +++ b/crates/fayalite/src/intern.rs @@ -1,7 +1,10 @@ // 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::{ConstBool, GenericConstBool}, +}; use bitvec::{ptr::BitPtr, slice::BitSlice, vec::BitVec}; use hashbrown::{hash_map::RawEntryMut, HashMap, HashTable}; use serde::{Deserialize, Serialize}; @@ -195,6 +198,7 @@ impl LazyInterned { pub trait InternedCompare { type InternedCompareKey: Ord + Hash; fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey; + fn interned_compare_key_weak(this: &std::sync::Weak) -> Self::InternedCompareKey; } /// Warning: doesn't do what you want with `T = dyn Trait`, @@ -268,6 +272,9 @@ impl InternedCompare for T { fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey { PtrEqWithMetadata(this) } + fn interned_compare_key_weak(this: &std::sync::Weak) -> Self::InternedCompareKey { + PtrEqWithMetadata(this.as_ptr()) + } } impl InternedCompare for [T] { @@ -275,6 +282,9 @@ impl InternedCompare for [T] { fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey { PtrEqWithMetadata(this) } + fn interned_compare_key_weak(this: &std::sync::Weak) -> Self::InternedCompareKey { + PtrEqWithMetadata(this.as_ptr()) + } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -285,6 +295,9 @@ impl InternedCompare for BitSlice { fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey { BitSlicePtrEq(this.as_bitptr(), this.len()) } + fn interned_compare_key_weak(_this: &std::sync::Weak) -> Self::InternedCompareKey { + unreachable!("not currently implementable since Weak can't be constructed") + } } impl InternedCompare for str { @@ -292,96 +305,341 @@ impl InternedCompare for str { fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey { PtrEqWithMetadata(this) } -} - -pub trait Intern: Any + Send + Sync { - fn intern(&self) -> Interned; - fn intern_sized(self) -> Interned - where - Self: Clone, - { - Self::intern_owned(self) - } - fn intern_owned(this: ::Owned) -> Interned - where - Self: ToOwned, - { - Self::intern_cow(Cow::Owned(this)) - } - fn intern_cow(this: Cow<'_, Self>) -> Interned - where - Self: ToOwned, - { - this.intern() + fn interned_compare_key_weak(this: &std::sync::Weak) -> Self::InternedCompareKey { + PtrEqWithMetadata(this.as_ptr()) } } -pub struct Interner { - map: Mutex>, +pub trait InternContext: 'static + Send + Sync + Hash + Ord + fmt::Debug + Clone { + type InternedImpl: 'static + Send + Sync + Clone; + type InternedGuardImpl: 'static + + Send + + Sync + + Clone + + Borrow; + type AllContextsAreIdentical: GenericConstBool; + fn interned_compare_key( + v: &Self::InternedImpl, + ) -> T::InternedCompareKey { + T::interned_compare_key_ref(Self::guard(v).borrow()) + } + fn guard( + v: &Self::InternedImpl, + ) -> Self::InternedGuardImpl; + fn try_guard( + v: &Self::InternedImpl, + ) -> Option>; + fn into_guard( + v: Self::InternedImpl, + ) -> Self::InternedGuardImpl { + Self::guard(&v) + } + fn unguard( + v: &Self::InternedGuardImpl, + ) -> Self::InternedImpl; + fn unguard_move( + v: Self::InternedGuardImpl, + ) -> Self::InternedImpl { + Self::unguard(&v) + } + fn alloc_str(&self, value: Cow<'_, str>) -> Self::InternedGuardImpl; + fn alloc_slice( + &self, + value: Cow<'_, [T]>, + ) -> Self::InternedGuardImpl<[T]>; + fn alloc_sized( + &self, + value: Cow<'_, T>, + ) -> Self::InternedGuardImpl; + fn interner(&self) -> &Interner; } -impl Interner { - fn get() -> &'static Interner { +pub trait BitSliceInternContext: InternContext { + fn alloc_bit_slice(&self, value: Cow<'_, BitSlice>) -> Self::InternedGuardImpl; +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] +pub struct GlobalContext; + +impl InternContext for GlobalContext { + type InternedImpl = &'static T; + type InternedGuardImpl = &'static T; + type AllContextsAreIdentical = ConstBool; + + fn guard( + v: &Self::InternedImpl, + ) -> Self::InternedGuardImpl { + *v + } + fn try_guard( + v: &Self::InternedImpl, + ) -> Option> { + Some(*v) + } + fn unguard( + v: &Self::InternedGuardImpl, + ) -> Self::InternedImpl { + *v + } + fn alloc_str(&self, value: Cow<'_, str>) -> Self::InternedGuardImpl { + value.into_owned().leak() + } + fn alloc_slice( + &self, + value: Cow<'_, [T]>, + ) -> Self::InternedGuardImpl<[T]> { + value.into_owned().leak() + } + fn alloc_sized( + &self, + value: Cow<'_, T>, + ) -> Self::InternedGuardImpl { + Box::leak(Box::new(value.into_owned())) + } + fn interner(&self) -> &Interner { static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new(); TYPE_ID_MAP.get_or_insert_default() } } -impl Default for Interner { +impl BitSliceInternContext for GlobalContext { + fn alloc_bit_slice(&self, value: Cow<'_, BitSlice>) -> Self::InternedGuardImpl { + value.into_owned().leak() + } +} + +#[derive(Clone)] +pub struct AGCContext(std::sync::Arc); + +impl AGCContext { + pub fn new() -> Self { + Self(std::sync::Arc::new(TypeIdMap::new())) + } +} + +impl Default for AGCContext { + fn default() -> Self { + Self::new() + } +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AGCContextId(*const ()); + +impl fmt::Debug for AGCContextId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl AGCContext { + pub fn id(&self) -> AGCContextId { + AGCContextId(std::sync::Arc::as_ptr(&self.0).cast()) + } +} + +impl Hash for AGCContext { + fn hash(&self, state: &mut H) { + self.id().hash(state); + } +} + +impl Ord for AGCContext { + fn cmp(&self, other: &Self) -> Ordering { + self.id().cmp(&other.id()) + } +} + +impl PartialOrd for AGCContext { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Eq for AGCContext {} + +impl PartialEq for AGCContext { + fn eq(&self, other: &Self) -> bool { + self.id().eq(&other.id()) + } +} + +impl fmt::Debug for AGCContext { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AGCContext") + .field("id", &self.id()) + .finish_non_exhaustive() + } +} + +impl InternContext for AGCContext { + type InternedImpl = std::sync::Weak; + type InternedGuardImpl = std::sync::Arc; + type AllContextsAreIdentical = ConstBool; + + fn interned_compare_key( + v: &Self::InternedImpl, + ) -> T::InternedCompareKey { + T::interned_compare_key_weak(v) + } + fn guard( + v: &Self::InternedImpl, + ) -> Self::InternedGuardImpl { + v.upgrade().expect("expired") + } + fn try_guard( + v: &Self::InternedImpl, + ) -> Option> { + v.upgrade() + } + fn unguard( + v: &Self::InternedGuardImpl, + ) -> Self::InternedImpl { + std::sync::Arc::downgrade(v) + } + fn alloc_str(&self, value: Cow<'_, str>) -> Self::InternedGuardImpl { + match value { + Cow::Borrowed(value) => value.into(), + Cow::Owned(value) => value.into(), + } + } + fn alloc_slice( + &self, + value: Cow<'_, [T]>, + ) -> Self::InternedGuardImpl<[T]> { + match value { + Cow::Borrowed(value) => value.into(), + Cow::Owned(value) => value.into(), + } + } + fn alloc_sized( + &self, + value: Cow<'_, T>, + ) -> Self::InternedGuardImpl { + std::sync::Arc::new(value.into_owned()) + } + fn interner(&self) -> &Interner { + self.0.get_or_insert_default() + } +} + +pub trait Intern: Any + Send + Sync { + fn intern_with_ctx(&self, context: &C) -> Interned; + fn intern_sized_with_ctx(self, context: &C) -> Interned + where + Self: Clone, + { + Self::intern_owned_with_ctx(self, context) + } + fn intern_owned_with_ctx(this: ::Owned, context: &C) -> Interned + where + Self: ToOwned, + { + Self::intern_cow_with_ctx(Cow::Owned(this), context) + } + fn intern_cow_with_ctx(this: Cow<'_, Self>, context: &C) -> Interned + where + Self: ToOwned, + { + this.intern_with_ctx(context) + } + fn intern(&self) -> Interned + where + C: InternContext> + Default, + { + self.intern_with_ctx(&C::default()) + } + fn intern_sized(self) -> Interned + where + Self: Clone, + C: InternContext> + Default, + { + self.intern_sized_with_ctx(&C::default()) + } + fn intern_owned(this: ::Owned) -> Interned + where + Self: ToOwned, + C: InternContext> + Default, + { + Self::intern_owned_with_ctx(this, &C::default()) + } + fn intern_cow(this: Cow<'_, Self>) -> Interned + where + Self: ToOwned, + C: InternContext> + Default, + { + Self::intern_cow_with_ctx(this, &C::default()) + } +} + +pub struct Interner { + map: Mutex, ()>>, + _phantom: PhantomData, +} + +impl Default for Interner { fn default() -> Self { Self { map: Default::default(), + _phantom: Default::default(), } } } -impl Interner { - fn intern) -> &'static T>( +impl Interner { + fn intern) -> C::InternedGuardImpl>( &self, alloc: F, value: Cow<'_, T>, - ) -> Interned { + ) -> Interned { 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 inner = match map + .raw_entry_mut() + .from_hash(hash, |k| k.borrow() == &*value) + { + RawEntryMut::Occupied(entry) => C::unguard(entry.key()), + RawEntryMut::Vacant(entry) => C::unguard( + entry + .insert_with_hasher(hash, alloc(value), (), |k| hasher.hash_one(k.borrow())) + .0, + ), }; - Interned { inner } + Interned { + inner, + _phantom: PhantomData, + } } } -impl Interner { - fn intern_sized(&self, value: Cow<'_, T>) -> Interned { - self.intern(|value| Box::leak(Box::new(value.into_owned())), value) +impl Interner { + fn intern_sized(&self, context: &C, value: Cow<'_, T>) -> Interned { + self.intern(|value| context.alloc_sized(value), value) } } -impl Interner<[T]> { - fn intern_slice(&self, value: Cow<'_, [T]>) -> Interned<[T]> { - self.intern(|value| value.into_owned().leak(), value) +impl Interner<[T], C> { + fn intern_slice(&self, context: &C, value: Cow<'_, [T]>) -> Interned<[T], C> { + self.intern(|value| context.alloc_slice(value), value) } } -impl Interner { - fn intern_bit_slice(&self, value: Cow<'_, BitSlice>) -> Interned { - self.intern(|value| value.into_owned().leak(), value) +impl Interner { + fn intern_bit_slice(&self, context: &C, value: Cow<'_, BitSlice>) -> Interned { + self.intern(|value| context.alloc_bit_slice(value), value) } } -impl Interner { - fn intern_str(&self, value: Cow<'_, str>) -> Interned { - self.intern(|value| value.into_owned().leak(), value) +impl Interner { + fn intern_str(&self, context: &C, value: Cow<'_, str>) -> Interned { + self.intern(|value| context.alloc_str(value), value) } } -pub struct Interned { - inner: &'static T, +pub struct Interned { + inner: C::InternedImpl, + _phantom: PhantomData<&'static C>, } macro_rules! forward_fmt_trait { @@ -392,9 +650,23 @@ macro_rules! forward_fmt_trait { } } - impl fmt::$Tr for Interned { + impl fmt::$Tr + for Interned + { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.fmt(f) + if let Some(guard) = C::try_guard(&self.inner) { + guard.borrow().fmt(f) + } else { + write!(f, "") + } + } + } + + impl fmt::$Tr + for Guard + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.borrow().fmt(f) } } }; @@ -410,16 +682,18 @@ forward_fmt_trait!(UpperExp); forward_fmt_trait!(UpperHex); #[derive(Clone, Debug)] -pub struct InternedSliceIter { - slice: Interned<[T]>, +pub struct InternedSliceIter { + slice: Interned<[T], C>, index: std::ops::Range, } -impl Iterator for InternedSliceIter { +impl Iterator for InternedSliceIter { type Item = T; fn next(&mut self) -> Option { - self.index.next().map(|index| self.slice[index].clone()) + self.index + .next() + .map(|index| self.slice.guard()[index].clone()) } fn size_hint(&self) -> (usize, Option) { @@ -427,186 +701,233 @@ impl Iterator for InternedSliceIter { } } -impl DoubleEndedIterator for InternedSliceIter { +impl DoubleEndedIterator + for InternedSliceIter +{ fn next_back(&mut self) -> Option { self.index .next_back() - .map(|index| self.slice[index].clone()) + .map(|index| self.slice.guard()[index].clone()) } } -impl FusedIterator for InternedSliceIter {} +impl FusedIterator for InternedSliceIter {} -impl ExactSizeIterator for InternedSliceIter {} +impl ExactSizeIterator + for InternedSliceIter +{ +} -impl IntoIterator for Interned<[T]> { +impl IntoIterator for Interned<[T], C> { type Item = T; - type IntoIter = InternedSliceIter; + type IntoIter = InternedSliceIter; fn into_iter(self) -> Self::IntoIter { InternedSliceIter { - index: 0..self.len(), + index: 0..self.guard().len(), slice: self, } } } -impl<'a, T: 'static + Send + Sync> IntoIterator for &'a Interned<[T]> { - type Item = &'a T; - type IntoIter = std::slice::Iter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.inner.iter() - } -} - -impl<'a, T: 'static + Send + Sync> IntoIterator for &'a mut Interned<[T]> { - type Item = &'a T; - type IntoIter = std::slice::Iter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.inner.iter() - } -} - -impl FromIterator for Interned<[I]> +impl<'a, T: 'static + Send + Sync, C: InternContext> IntoIterator for &'a Interned<[T], C> where - [I]: Intern, + C::InternedImpl<[T]>: Borrow<[T]>, +{ + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.inner.borrow().iter() + } +} + +impl<'a, T: 'static + Send + Sync, C: InternContext> IntoIterator for &'a mut Interned<[T], C> +where + C::InternedImpl<[T]>: Borrow<[T]>, +{ + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.inner.borrow().iter() + } +} + +impl> + Default> + FromIterator for Interned<[I], C> +where + [I]: Intern, { fn from_iter>(iter: T) -> Self { Intern::intern_owned(Vec::from_iter(iter)) } } -impl From> for Vec { - fn from(value: Interned<[T]>) -> Self { - Vec::from(&*value) +impl From> for Vec { + fn from(value: Interned<[T], C>) -> Self { + Vec::from(&*value.guard()) } } -impl From> for Box<[T]> { - fn from(value: Interned<[T]>) -> Self { - Box::from(&*value) +impl From> for Box<[T]> { + fn from(value: Interned<[T], C>) -> Self { + Box::from(&*value.guard()) } } -impl From> for String { - fn from(value: Interned) -> Self { - String::from(&*value) +impl From> for String { + fn from(value: Interned) -> Self { + String::from(&*value.guard()) } } -impl Default for Interned<[I]> +impl> + Default> Default + for Interned<[I], C> where - [I]: Intern, + [I]: Intern, { fn default() -> Self { [][..].intern() } } -impl Default for Interned { +impl> + Default> Default + for Interned +where + str: Intern, +{ fn default() -> Self { "".intern() } } -impl Default for Interned { +impl> + Default> Default + for Interned +where + BitSlice: Intern, +{ fn default() -> Self { <&BitSlice>::default().intern() } } -impl Default for Interned +impl> + Default> + Default for Interned where - I: Intern, + I: Intern, { fn default() -> Self { I::default().intern() } } -impl Interned { +impl Interned { pub fn cast_unchecked( this: Self, - f: impl FnOnce(&'static T) -> &'static U, - ) -> Interned { + f: impl FnOnce(C::InternedImpl) -> C::InternedImpl, + ) -> Interned { Interned { inner: f(this.inner), + _phantom: PhantomData, } } pub fn try_cast_unchecked( this: Self, - f: impl FnOnce(&'static T) -> Result<&'static U, E>, - ) -> Result, E> { + f: impl FnOnce(C::InternedImpl) -> Result, E>, + ) -> Result, E> { Ok(Interned { inner: f(this.inner)?, + _phantom: PhantomData, }) } - pub fn into_inner(this: Self) -> &'static T { + pub fn into_inner(this: Self) -> C::InternedImpl { this.inner } - pub fn get_ref(this: &Self) -> &&'static T { + pub fn get_ref(this: &Self) -> &C::InternedImpl { &this.inner } -} - -impl Clone for Interned { - fn clone(&self) -> Self { - *self + pub fn guard(&self) -> Guard { + Guard { + inner: C::guard(&self.inner), + _phantom: PhantomData, + } } } -impl Copy for Interned where &'static T: Copy {} +impl Clone for Interned { + fn clone(&self) -> Self { + Interned { + inner: self.inner.clone(), + _phantom: PhantomData, + } + } +} -impl Deref for Interned +impl Copy for Interned where + C::InternedImpl: Copy +{ +} + +impl Deref for Interned where - &'static T: Borrow, + C::InternedImpl: Borrow, { type Target = T; fn deref(&self) -> &Self::Target { - self.inner + self.inner.borrow() } } -impl PartialEq for Interned { +impl PartialEq + for Interned +{ fn eq(&self, other: &Self) -> bool { - T::interned_compare_key_ref(self.inner) == T::interned_compare_key_ref(other.inner) + ::interned_compare_key(&self.inner) + == ::interned_compare_key(&other.inner) } } -impl Eq for Interned {} +impl Eq for Interned {} -impl PartialOrd for Interned { +impl PartialOrd + for Interned +{ fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for Interned { +impl Ord for Interned { fn cmp(&self, other: &Self) -> Ordering { - T::interned_compare_key_ref(self.inner).cmp(&T::interned_compare_key_ref(other.inner)) + ::interned_compare_key(&self.inner) + .cmp(&::interned_compare_key(&other.inner)) } } -impl Hash for Interned { +impl Hash + for Interned +{ fn hash(&self, state: &mut H) { - T::interned_compare_key_ref(self.inner).hash(state); + ::interned_compare_key(&self.inner).hash(state); } } -impl Serialize for Interned { +impl Serialize for Interned { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { - T::serialize(self, serializer) + self.guard().serialize(serializer) } } -impl<'de, T: 'static + Send + Sync + Deserialize<'de> + Clone + Intern> Deserialize<'de> - for Interned +impl< + 'de, + T: 'static + Send + Sync + Deserialize<'de> + Clone + Intern, + C: InternContext> + Default, + > Deserialize<'de> for Interned { fn deserialize(deserializer: D) -> Result where @@ -616,9 +937,13 @@ impl<'de, T: 'static + Send + Sync + Deserialize<'de> + Clone + Intern> Deserial } } -impl<'de, T: 'static + Send + Sync + Clone> Deserialize<'de> for Interned<[T]> +impl< + 'de, + T: 'static + Send + Sync + Clone, + C: InternContext> + Default, + > Deserialize<'de> for Interned<[T], C> where - [T]: Intern, + [T]: Intern, Vec: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result @@ -629,7 +954,11 @@ where } } -impl<'de> Deserialize<'de> for Interned { +impl<'de, C: BitSliceInternContext> + Default> + Deserialize<'de> for Interned +where + BitSlice: Intern, +{ fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -638,7 +967,11 @@ impl<'de> Deserialize<'de> for Interned { } } -impl<'de> Deserialize<'de> for Interned { +impl<'de, C: InternContext> + Default> Deserialize<'de> + for Interned +where + str: Intern, +{ fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -647,83 +980,175 @@ impl<'de> Deserialize<'de> for Interned { } } -impl Intern for T { - fn intern(&self) -> Interned { - Self::intern_cow(Cow::Borrowed(self)) - } +pub struct Guard { + inner: C::InternedGuardImpl, + _phantom: PhantomData<&'static C>, +} - fn intern_owned(this: ::Owned) -> Interned - where - Self: ToOwned, - { - Self::intern_cow(Cow::Owned(this)) +impl Guard { + pub fn cast_unchecked( + this: Self, + f: impl FnOnce(C::InternedGuardImpl) -> C::InternedGuardImpl, + ) -> Guard { + Guard { + inner: f(this.inner), + _phantom: PhantomData, + } } - - fn intern_cow(this: Cow<'_, Self>) -> Interned - where - Self: ToOwned, - { - Interner::get().intern_sized(this) + pub fn try_cast_unchecked( + this: Self, + f: impl FnOnce(C::InternedGuardImpl) -> Result, E>, + ) -> Result, E> { + Ok(Guard { + inner: f(this.inner)?, + _phantom: PhantomData, + }) + } + pub fn into_inner(this: Self) -> C::InternedGuardImpl { + this.inner + } + pub fn get_ref(this: &Self) -> &C::InternedGuardImpl { + &this.inner + } + pub fn unguard(&self) -> Interned { + Interned { + inner: C::unguard(&self.inner), + _phantom: PhantomData, + } } } -impl Intern for [T] { - fn intern(&self) -> Interned { - Self::intern_cow(Cow::Borrowed(self)) - } - - fn intern_owned(this: ::Owned) -> Interned - where - Self: ToOwned, - { - Self::intern_cow(Cow::Owned(this)) - } - - fn intern_cow(this: Cow<'_, Self>) -> Interned - where - Self: ToOwned, - { - Interner::get().intern_slice(this) +impl Clone for Guard { + fn clone(&self) -> Self { + Guard { + inner: self.inner.clone(), + _phantom: PhantomData, + } } } -impl Intern for BitSlice { - fn intern(&self) -> Interned { - Self::intern_cow(Cow::Borrowed(self)) - } +impl Copy for Guard where + C::InternedGuardImpl: Copy +{ +} - fn intern_owned(this: ::Owned) -> Interned - where - Self: ToOwned, - { - Self::intern_cow(Cow::Owned(this)) - } +impl Deref for Guard { + type Target = T; - fn intern_cow(this: Cow<'_, Self>) -> Interned - where - Self: ToOwned, - { - Interner::get().intern_bit_slice(this) + fn deref(&self) -> &Self::Target { + self.inner.borrow() } } -impl Intern for str { - fn intern(&self) -> Interned { - Self::intern_cow(Cow::Borrowed(self)) +impl PartialEq + for Guard +{ + fn eq(&self, other: &Self) -> bool { + T::interned_compare_key_ref(self.inner.borrow()) + == T::interned_compare_key_ref(other.inner.borrow()) + } +} + +impl Eq for Guard {} + +impl PartialOrd + for Guard +{ + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Guard { + fn cmp(&self, other: &Self) -> Ordering { + T::interned_compare_key_ref(self.inner.borrow()) + .cmp(&T::interned_compare_key_ref(other.inner.borrow())) + } +} + +impl Hash for Guard { + fn hash(&self, state: &mut H) { + T::interned_compare_key_ref(self.inner.borrow()).hash(state); + } +} + +impl Intern for T { + fn intern_with_ctx(&self, context: &C) -> Interned { + Self::intern_cow_with_ctx(Cow::Borrowed(self), context) } - fn intern_owned(this: ::Owned) -> Interned + fn intern_owned_with_ctx(this: ::Owned, context: &C) -> Interned where Self: ToOwned, { - Self::intern_cow(Cow::Owned(this)) + Self::intern_cow_with_ctx(Cow::Owned(this), context) } - fn intern_cow(this: Cow<'_, Self>) -> Interned + fn intern_cow_with_ctx(this: Cow<'_, Self>, context: &C) -> Interned where Self: ToOwned, { - Interner::get().intern_str(this) + context.interner().intern_sized(context, this) + } +} + +impl Intern for [T] { + fn intern_with_ctx(&self, context: &C) -> Interned { + Self::intern_cow_with_ctx(Cow::Borrowed(self), context) + } + + fn intern_owned_with_ctx(this: ::Owned, context: &C) -> Interned + where + Self: ToOwned, + { + Self::intern_cow_with_ctx(Cow::Owned(this), context) + } + + fn intern_cow_with_ctx(this: Cow<'_, Self>, context: &C) -> Interned + where + Self: ToOwned, + { + context.interner().intern_slice(context, this) + } +} + +impl Intern for BitSlice { + fn intern_with_ctx(&self, context: &C) -> Interned { + Self::intern_cow_with_ctx(Cow::Borrowed(self), context) + } + + fn intern_owned_with_ctx(this: ::Owned, context: &C) -> Interned + where + Self: ToOwned, + { + Self::intern_cow_with_ctx(Cow::Owned(this), context) + } + + fn intern_cow_with_ctx(this: Cow<'_, Self>, context: &C) -> Interned + where + Self: ToOwned, + { + context.interner().intern_bit_slice(context, this) + } +} + +impl Intern for str { + fn intern_with_ctx(&self, context: &C) -> Interned { + Self::intern_cow_with_ctx(Cow::Borrowed(self), context) + } + + fn intern_owned_with_ctx(this: ::Owned, context: &C) -> Interned + where + Self: ToOwned, + { + Self::intern_cow_with_ctx(Cow::Owned(this), context) + } + + fn intern_cow_with_ctx(this: Cow<'_, Self>, context: &C) -> Interned + where + Self: ToOwned, + { + context.interner().intern_str(context, this) } } diff --git a/crates/fayalite/src/memory.rs b/crates/fayalite/src/memory.rs index f583a8c..1762f57 100644 --- a/crates/fayalite/src/memory.rs +++ b/crates/fayalite/src/memory.rs @@ -634,7 +634,7 @@ impl Mem { self.0.source_location } pub fn array_type(self) -> ArrayType { - self.0.array_type + self.0.array_type.clone() } pub fn initial_value(self) -> Option> { self.0.initial_value @@ -987,7 +987,7 @@ impl MemBuilder { #[allow(clippy::result_unit_err)] pub fn get_array_type(&self) -> Result, ()> { Ok(ArrayType::new( - self.mem_element_type, + self.mem_element_type.clone(), Len::from_usize(self.get_depth()?), )) } diff --git a/crates/fayalite/src/module.rs b/crates/fayalite/src/module.rs index 7d6949c..2ba3800 100644 --- a/crates/fayalite/src/module.rs +++ b/crates/fayalite/src/module.rs @@ -607,10 +607,6 @@ impl BlockStack { pub struct Id(NonZeroU64); impl Id { - #[allow( - clippy::new_without_default, - reason = "returns a different value each time, so there isn't really a default value" - )] pub fn new() -> Self { static NEXT_ID: AtomicU64 = AtomicU64::new(1); Self( @@ -949,7 +945,7 @@ impl From> for NormalModuleBody { Stmt::Declaration(decl) => { let annotations = annotations_map .remove(&decl) - .map(Intern::intern_owned) + .map(|v| Intern::intern_owned(v)) .unwrap_or_default(); match decl { StmtDeclaration::Wire(StmtWire { @@ -1619,7 +1615,10 @@ impl AssertValidityState { let module = self.module; if block == 0 { for module_io in &*module.module_io { - self.insert_new_base(TargetBase::intern_sized(module_io.module_io.into()), block); + self.insert_new_base( + TargetBase::intern_sized(module_io.module_io.clone().into()), + block, + ); } } let Block { memories, stmts } = self.blocks[block]; @@ -1935,7 +1934,7 @@ impl ModuleBuilder { let module_io = module_io.canonical(); let mut impl_ = self.impl_.borrow_mut(); let impl_ = &mut *impl_; - impl_.io_indexes.insert(module_io, impl_.io.len()); + impl_.io_indexes.insert(module_io.clone(), impl_.io.len()); impl_.io.push(AnnotatedModuleIO { annotations: vec![], module_io, @@ -2479,7 +2478,7 @@ pub fn memory_array_with_loc( mem_array_type: ArrayType, source_location: SourceLocation, ) -> MemBuilder { - let mut retval = memory_impl(name, mem_array_type.element(), source_location); + let mut retval = memory_impl(name, mem_array_type.element().clone(), source_location); retval.depth(mem_array_type.len()); retval } diff --git a/crates/fayalite/src/module/transform/simplify_enums.rs b/crates/fayalite/src/module/transform/simplify_enums.rs index bb57cf0..f398006 100644 --- a/crates/fayalite/src/module/transform/simplify_enums.rs +++ b/crates/fayalite/src/module/transform/simplify_enums.rs @@ -271,12 +271,12 @@ impl State { .into()), EnumTypeState::TagUIntAndBody(_) => { let int_tag_expr = Expr::>::from_canonical(folded_expr).tag; - Ok(match_int_tag(int_tag_expr, source_location, folded_blocks).into()) + Ok(match_int_tag(int_tag_expr, source_location, &folded_blocks).into()) } EnumTypeState::UInt(_) => { let int_tag_expr = Expr::::from_canonical(folded_expr) [..unfolded_enum_type.discriminant_bit_width()]; - Ok(match_int_tag(int_tag_expr, source_location, folded_blocks).into()) + Ok(match_int_tag(int_tag_expr, source_location, &folded_blocks).into()) } EnumTypeState::Unchanged => Ok(StmtMatch { expr: Expr::from_canonical(folded_expr), @@ -929,10 +929,13 @@ impl Folder for State { unreachable!() } - fn fold_enum_literal>( + fn fold_enum_literal( &mut self, _v: ops::EnumLiteral, - ) -> Result, Self::Error> { + ) -> Result, Self::Error> + where + T: Fold, + { unreachable!() } diff --git a/crates/fayalite/src/module/transform/simplify_memories.rs b/crates/fayalite/src/module/transform/simplify_memories.rs index e8f9cbf..71e459c 100644 --- a/crates/fayalite/src/module/transform/simplify_memories.rs +++ b/crates/fayalite/src/module/transform/simplify_memories.rs @@ -766,7 +766,7 @@ impl ModuleState { output_stmts.push( StmtWire { annotations: Default::default(), - wire: canonical_wire, + wire: canonical_wire.clone(), } .into(), ); diff --git a/crates/fayalite/src/ty.rs b/crates/fayalite/src/ty.rs index 69080c9..380d2e6 100644 --- a/crates/fayalite/src/ty.rs +++ b/crates/fayalite/src/ty.rs @@ -330,6 +330,6 @@ impl Index for AsMaskWithoutGenerics { type Output = T::MaskType; fn index(&self, ty: T) -> &Self::Output { - Interned::into_inner(Intern::intern_sized(ty.mask_type())) + Interned::<_>::into_inner(Intern::intern_sized(ty.mask_type())) } } diff --git a/crates/fayalite/src/util/scoped_ref.rs b/crates/fayalite/src/util/scoped_ref.rs index 27f2f89..7705377 100644 --- a/crates/fayalite/src/util/scoped_ref.rs +++ b/crates/fayalite/src/util/scoped_ref.rs @@ -106,9 +106,3 @@ impl ScopedRef { self.0.with_opt(f) } } - -impl Default for ScopedRef { - fn default() -> Self { - Self::new() - } -} diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index 222f7ba..b0b1fb6 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -2258,7 +2258,7 @@ pub fn check_memory_of_bundle() { let wmask: (Bool, Bool) = m.input(); #[hdl] let clk: Clock = m.input(); - let mem_init = Vec::from_iter((0..0x10u8).map(|i| (i ^ 3, (i ^ (i / 2)).cast_to_static()))); + let mem_init = Vec::from_iter((0..0x10u8).map(|i| (i ^ 3, (i ^ i / 2).cast_to_static()))); #[hdl] let mut mem = memory_with_init(mem_init); let read_port = mem.new_read_port();