forked from libre-chip/fayalite
speed up LazyInterned by redoing caching using RwLock and add a thread-local cache
This commit is contained in:
parent
9db3240644
commit
1bc835803b
4 changed files with 189 additions and 107 deletions
|
|
@ -109,14 +109,42 @@ impl<T: StaticType, Len: KnownSize> Default for ArrayType<T, Len> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MakeType<T: StaticType>(Interned<T>);
|
||||||
|
|
||||||
|
impl<T: StaticType> From<MakeType<T>> for Interned<T> {
|
||||||
|
fn from(value: MakeType<T>) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: StaticType> Default for MakeType<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(T::TYPE.intern_sized())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MakeMaskType<T: StaticType>(Interned<T::MaskType>);
|
||||||
|
|
||||||
|
impl<T: StaticType> From<MakeMaskType<T>> for Interned<T::MaskType> {
|
||||||
|
fn from(value: MakeMaskType<T>) -> Self {
|
||||||
|
value.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: StaticType> Default for MakeMaskType<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self(T::MASK_TYPE.intern_sized())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: StaticType, Len: KnownSize> StaticType for ArrayType<T, Len> {
|
impl<T: StaticType, Len: KnownSize> StaticType for ArrayType<T, Len> {
|
||||||
const TYPE: Self = Self {
|
const TYPE: Self = Self {
|
||||||
element: LazyInterned::new_lazy(&|| T::TYPE.intern_sized()),
|
element: LazyInterned::new_const::<MakeType<T>>(),
|
||||||
len: Len::SIZE,
|
len: Len::SIZE,
|
||||||
type_properties: Self::TYPE_PROPERTIES,
|
type_properties: Self::TYPE_PROPERTIES,
|
||||||
};
|
};
|
||||||
const MASK_TYPE: Self::MaskType = ArrayType::<T::MaskType, Len> {
|
const MASK_TYPE: Self::MaskType = ArrayType::<T::MaskType, Len> {
|
||||||
element: LazyInterned::new_lazy(&|| T::MASK_TYPE.intern_sized()),
|
element: LazyInterned::new_const::<MakeMaskType<T>>(),
|
||||||
len: Len::SIZE,
|
len: Len::SIZE,
|
||||||
type_properties: Self::MASK_TYPE_PROPERTIES,
|
type_properties: Self::MASK_TYPE_PROPERTIES,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
borrow::{Borrow, Cow},
|
borrow::{Borrow, Cow},
|
||||||
|
cell::RefCell,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
ffi::{OsStr, OsString},
|
ffi::{OsStr, OsString},
|
||||||
fmt,
|
fmt,
|
||||||
hash::{BuildHasher, Hash, Hasher},
|
hash::{BuildHasher, Hash, Hasher},
|
||||||
iter::FusedIterator,
|
iter::FusedIterator,
|
||||||
marker::PhantomData,
|
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::RwLock,
|
sync::RwLock,
|
||||||
|
|
@ -23,51 +23,172 @@ use std::{
|
||||||
mod interner;
|
mod interner;
|
||||||
mod type_map;
|
mod type_map;
|
||||||
|
|
||||||
pub trait LazyInternedTrait<T: ?Sized + Send + Sync + 'static>: Send + Sync + Any {
|
/// invariant: T must be zero-sized, `type_id` is unique for every possible T value.
|
||||||
fn get(&self) -> Interned<T>;
|
struct LazyInternedLazyInner<T: ?Sized + 'static> {
|
||||||
|
type_id: TypeId,
|
||||||
|
value: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static, F: ?Sized + Fn() -> Interned<T> + Send + Sync + Any>
|
impl<T: ?Sized + 'static> Hash for LazyInternedLazyInner<T> {
|
||||||
LazyInternedTrait<T> for F
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
{
|
let Self { type_id, value: _ } = self;
|
||||||
fn get(&self) -> Interned<T> {
|
type_id.hash(state);
|
||||||
self()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
impl<T: ?Sized + 'static> PartialEq for LazyInternedLazyInner<T> {
|
||||||
pub struct LazyInternedFn<T: ?Sized + Send + Sync + 'static>(pub &'static dyn LazyInternedTrait<T>);
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
let Self { type_id, value: _ } = self;
|
||||||
|
*type_id == other.type_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static> Copy for LazyInternedFn<T> {}
|
impl<T: ?Sized + 'static> Eq for LazyInternedLazyInner<T> {}
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static> Clone for LazyInternedFn<T> {
|
impl<T: ?Sized + 'static> fmt::Debug for LazyInternedLazyInner<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("LazyInternedLazyInner")
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + 'static> LazyInternedLazyInner<T> {
|
||||||
|
const fn new(value: T) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
const { assert!(size_of::<T>() == 0) };
|
||||||
|
Self {
|
||||||
|
type_id: TypeId::of::<T>(),
|
||||||
|
value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LazyInternedLazy<T: ?Sized + Send + Sync + 'static>(
|
||||||
|
&'static LazyInternedLazyInner<dyn Fn() -> Interned<T> + Send + Sync>,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<T: ?Sized + Send + Sync + 'static> LazyInternedLazy<T> {
|
||||||
|
pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
|
||||||
|
Self(&const { LazyInternedLazyInner::new(|| V::default().into()) })
|
||||||
|
}
|
||||||
|
pub const fn new_const_default() -> Self
|
||||||
|
where
|
||||||
|
Interned<T>: Default,
|
||||||
|
{
|
||||||
|
Self::new_const::<Interned<T>>()
|
||||||
|
}
|
||||||
|
pub fn interned(self) -> Interned<T> {
|
||||||
|
struct Map(hashbrown::HashTable<(TypeId, &'static (dyn Any + Send + Sync))>);
|
||||||
|
impl Map {
|
||||||
|
const EMPTY: Self = Self(hashbrown::HashTable::new());
|
||||||
|
fn get<T: ?Sized + Send + Sync + 'static>(
|
||||||
|
&self,
|
||||||
|
lazy_interned_lazy: LazyInternedLazy<T>,
|
||||||
|
hash: u64,
|
||||||
|
) -> Option<&'static Interned<T>> {
|
||||||
|
let &(_, v) = self.0.find(hash, |v| v.0 == lazy_interned_lazy.0.type_id)?;
|
||||||
|
let Some(retval) = v.downcast_ref::<Interned<T>>() else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
Some(retval)
|
||||||
|
}
|
||||||
|
fn get_or_insert<T: ?Sized + Send + Sync + 'static>(
|
||||||
|
&mut self,
|
||||||
|
lazy_interned_lazy: LazyInternedLazy<T>,
|
||||||
|
hash: u64,
|
||||||
|
v: &'static Interned<T>,
|
||||||
|
) -> &'static Interned<T> {
|
||||||
|
let entry = self
|
||||||
|
.0
|
||||||
|
.entry(
|
||||||
|
hash,
|
||||||
|
|&(k, _)| k == lazy_interned_lazy.0.type_id,
|
||||||
|
|&(k, _)| type_map::TypeIdBuildHasher.hash_one(k),
|
||||||
|
)
|
||||||
|
.or_insert_with(|| (lazy_interned_lazy.0.type_id, v));
|
||||||
|
let &(_, v) = entry.get();
|
||||||
|
let Some(retval) = v.downcast_ref::<Interned<T>>() else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static GLOBAL_CACHE: RwLock<Map> = RwLock::new(Map::EMPTY);
|
||||||
|
#[cold]
|
||||||
|
fn insert_in_thread_local_cache<T: ?Sized + Send + Sync + 'static>(
|
||||||
|
cache: &RefCell<Map>,
|
||||||
|
this: LazyInternedLazy<T>,
|
||||||
|
hash: u64,
|
||||||
|
) -> Interned<T> {
|
||||||
|
let read_lock = GLOBAL_CACHE.read().unwrap();
|
||||||
|
let v = read_lock.get(this, hash);
|
||||||
|
drop(read_lock);
|
||||||
|
let v = v.unwrap_or_else(|| {
|
||||||
|
let v = Box::leak(Box::new((this.0.value)()));
|
||||||
|
GLOBAL_CACHE.write().unwrap().get_or_insert(this, hash, v)
|
||||||
|
});
|
||||||
|
*cache.borrow_mut().get_or_insert(this, hash, v)
|
||||||
|
}
|
||||||
|
thread_local! {
|
||||||
|
static THREAD_LOCAL_CACHE: RefCell<Map> = const { RefCell::new(Map::EMPTY) };
|
||||||
|
}
|
||||||
|
let hash = type_map::TypeIdBuildHasher.hash_one(self.0.type_id);
|
||||||
|
THREAD_LOCAL_CACHE.with(|cache| {
|
||||||
|
let borrow = cache.borrow();
|
||||||
|
if let Some(v) = borrow.get(self, hash) {
|
||||||
|
*v
|
||||||
|
} else {
|
||||||
|
drop(borrow);
|
||||||
|
insert_in_thread_local_cache(cache, self, hash)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized + Send + Sync + 'static> Copy for LazyInternedLazy<T> {}
|
||||||
|
|
||||||
|
impl<T: ?Sized + Send + Sync + 'static> Clone for LazyInternedLazy<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static> Hash for LazyInternedFn<T> {
|
impl<T: ?Sized + Send + Sync + 'static> Hash for LazyInternedLazy<T> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.0.get_ptr_eq_with_type_id().hash(state);
|
self.0.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static> Eq for LazyInternedFn<T> {}
|
impl<T: ?Sized + Send + Sync + 'static> Eq for LazyInternedLazy<T> {}
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static> PartialEq for LazyInternedFn<T> {
|
impl<T: ?Sized + Send + Sync + 'static> PartialEq for LazyInternedLazy<T> {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.0.get_ptr_eq_with_type_id() == other.0.get_ptr_eq_with_type_id()
|
self.0 == other.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum LazyInterned<T: ?Sized + Send + Sync + 'static> {
|
pub enum LazyInterned<T: ?Sized + Send + Sync + 'static> {
|
||||||
Interned(Interned<T>),
|
Interned(Interned<T>),
|
||||||
Lazy(LazyInternedFn<T>),
|
Lazy(LazyInternedLazy<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Send + Sync + 'static> LazyInterned<T> {
|
impl<T: ?Sized + Send + Sync + 'static> LazyInterned<T> {
|
||||||
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self {
|
pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
|
||||||
Self::Lazy(LazyInternedFn(v))
|
Self::Lazy(LazyInternedLazy::new_const::<V>())
|
||||||
|
}
|
||||||
|
pub const fn new_const_default() -> Self
|
||||||
|
where
|
||||||
|
Interned<T>: Default,
|
||||||
|
{
|
||||||
|
Self::new_const::<Interned<T>>()
|
||||||
|
}
|
||||||
|
pub fn interned(self) -> Interned<T> {
|
||||||
|
match self {
|
||||||
|
Self::Interned(retval) => retval,
|
||||||
|
Self::Lazy(retval) => retval.interned(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +200,7 @@ impl<T: ?Sized + Sync + Send + 'static> Clone for LazyInterned<T> {
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static> Copy for LazyInterned<T> {}
|
impl<T: ?Sized + Sync + Send + 'static> Copy for LazyInterned<T> {}
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Deref for LazyInterned<T> {
|
impl<T: ?Sized + Sync + Send + 'static> Deref for LazyInterned<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|
@ -87,9 +208,9 @@ impl<T: ?Sized + Sync + Send + 'static + Intern> Deref for LazyInterned<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Eq for LazyInterned<T> where Interned<T>: Eq {}
|
impl<T: ?Sized + Sync + Send + 'static> Eq for LazyInterned<T> where Interned<T>: Eq {}
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static + Intern> PartialEq for LazyInterned<T>
|
impl<T: ?Sized + Sync + Send + 'static> PartialEq for LazyInterned<T>
|
||||||
where
|
where
|
||||||
Interned<T>: PartialEq,
|
Interned<T>: PartialEq,
|
||||||
{
|
{
|
||||||
|
|
@ -98,7 +219,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Ord for LazyInterned<T>
|
impl<T: ?Sized + Sync + Send + 'static> Ord for LazyInterned<T>
|
||||||
where
|
where
|
||||||
Interned<T>: Ord,
|
Interned<T>: Ord,
|
||||||
{
|
{
|
||||||
|
|
@ -107,7 +228,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static + Intern> PartialOrd for LazyInterned<T>
|
impl<T: ?Sized + Sync + Send + 'static> PartialOrd for LazyInterned<T>
|
||||||
where
|
where
|
||||||
Interned<T>: PartialOrd,
|
Interned<T>: PartialOrd,
|
||||||
{
|
{
|
||||||
|
|
@ -116,7 +237,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static + Intern> Hash for LazyInterned<T>
|
impl<T: ?Sized + Sync + Send + 'static> Hash for LazyInterned<T>
|
||||||
where
|
where
|
||||||
Interned<T>: Hash,
|
Interned<T>: Hash,
|
||||||
{
|
{
|
||||||
|
|
@ -125,77 +246,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + Sync + Send + 'static> LazyInterned<T> {
|
|
||||||
pub fn interned(self) -> Interned<T>
|
|
||||||
where
|
|
||||||
T: Intern,
|
|
||||||
{
|
|
||||||
struct MemoizeInterned<T: ?Sized + Intern>(PhantomData<T>);
|
|
||||||
|
|
||||||
impl<T: ?Sized + Intern> Hash for MemoizeInterned<T> {
|
|
||||||
fn hash<H: Hasher>(&self, _state: &mut H) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized + Intern> PartialEq for MemoizeInterned<T> {
|
|
||||||
fn eq(&self, _other: &Self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized + Intern> Eq for MemoizeInterned<T> {}
|
|
||||||
|
|
||||||
impl<T: ?Sized + Intern> Clone for MemoizeInterned<T> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized + Intern> Copy for MemoizeInterned<T> {}
|
|
||||||
|
|
||||||
impl<T: ?Sized + Intern> MemoizeGeneric for MemoizeInterned<T> {
|
|
||||||
type InputRef<'a> = LazyInternedFn<T>;
|
|
||||||
|
|
||||||
type InputOwned = LazyInternedFn<T>;
|
|
||||||
|
|
||||||
type InputCow<'a> = LazyInternedFn<T>;
|
|
||||||
|
|
||||||
type Output = Interned<T>;
|
|
||||||
|
|
||||||
fn input_eq(a: Self::InputRef<'_>, b: Self::InputRef<'_>) -> bool {
|
|
||||||
a == b
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_borrow(input: &Self::InputOwned) -> Self::InputRef<'_> {
|
|
||||||
*input
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_cow_into_owned(input: Self::InputCow<'_>) -> Self::InputOwned {
|
|
||||||
input
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_cow_borrow<'a>(input: &'a Self::InputCow<'_>) -> Self::InputRef<'a> {
|
|
||||||
*input
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_cow_from_owned<'a>(input: Self::InputOwned) -> Self::InputCow<'a> {
|
|
||||||
input
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_cow_from_ref(input: Self::InputRef<'_>) -> Self::InputCow<'_> {
|
|
||||||
input
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner(self, input: Self::InputRef<'_>) -> Self::Output {
|
|
||||||
input.0.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match self {
|
|
||||||
Self::Interned(retval) => retval,
|
|
||||||
Self::Lazy(retval) => MemoizeInterned(PhantomData).get(retval),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait InternedCompare {
|
pub trait InternedCompare {
|
||||||
type InternedCompareKey: Ord + Hash;
|
type InternedCompareKey: Ord + Hash;
|
||||||
fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey;
|
fn interned_compare_key_ref(this: &Self) -> Self::InternedCompareKey;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
sync::RwLock,
|
sync::RwLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeIdHasher(u64);
|
pub(crate) struct TypeIdHasher(u64);
|
||||||
|
|
||||||
// assumes TypeId has at least 64 bits that is a good hash
|
// assumes TypeId has at least 64 bits that is a good hash
|
||||||
impl Hasher for TypeIdHasher {
|
impl Hasher for TypeIdHasher {
|
||||||
|
|
@ -63,7 +63,7 @@ impl Hasher for TypeIdHasher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TypeIdBuildHasher;
|
pub(crate) struct TypeIdBuildHasher;
|
||||||
|
|
||||||
impl BuildHasher for TypeIdBuildHasher {
|
impl BuildHasher for TypeIdBuildHasher {
|
||||||
type Hasher = TypeIdHasher;
|
type Hasher = TypeIdHasher;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
expr::{Expr, HdlPartialEqImpl, HdlPartialOrdImpl, ToExpr, ValueType},
|
expr::{Expr, HdlPartialEqImpl, HdlPartialOrdImpl, ToExpr, ValueType},
|
||||||
int::Bool,
|
int::Bool,
|
||||||
intern::{Intern, Interned, InternedCompare, LazyInterned, LazyInternedTrait, Memoize},
|
intern::{Intern, Interned, InternedCompare, LazyInterned, Memoize},
|
||||||
sim::value::{SimValue, ToSimValue, ToSimValueWithType},
|
sim::value::{SimValue, ToSimValue, ToSimValueWithType},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
ty::{
|
ty::{
|
||||||
|
|
@ -240,11 +240,17 @@ impl<T: ?Sized + PhantomConstValue> PhantomConst<T> {
|
||||||
{
|
{
|
||||||
Self::new_interned(value.intern_deref())
|
Self::new_interned(value.intern_deref())
|
||||||
}
|
}
|
||||||
pub const fn new_lazy(v: &'static dyn LazyInternedTrait<T>) -> Self {
|
pub const fn new_const<V: Default + Into<Interned<T>>>() -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: LazyInterned::new_lazy(v),
|
value: LazyInterned::new_const::<V>(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub const fn new_const_default() -> Self
|
||||||
|
where
|
||||||
|
Interned<T>: Default,
|
||||||
|
{
|
||||||
|
Self::new_const::<Interned<T>>()
|
||||||
|
}
|
||||||
pub fn get(self) -> Interned<T> {
|
pub fn get(self) -> Interned<T> {
|
||||||
self.value.interned()
|
self.value.interned()
|
||||||
}
|
}
|
||||||
|
|
@ -334,9 +340,7 @@ impl<T: ?Sized + PhantomConstValue> StaticType for PhantomConst<T>
|
||||||
where
|
where
|
||||||
Interned<T>: Default,
|
Interned<T>: Default,
|
||||||
{
|
{
|
||||||
const TYPE: Self = PhantomConst {
|
const TYPE: Self = Self::new_const_default();
|
||||||
value: LazyInterned::new_lazy(&Interned::<T>::default),
|
|
||||||
};
|
|
||||||
const MASK_TYPE: Self::MaskType = ();
|
const MASK_TYPE: Self::MaskType = ();
|
||||||
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
||||||
const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue