runtime: make ValueVariant lifetime-generic and add TryFrom<Value> conversions

This commit is contained in:
2026-08-22 18:49:40 +08:00
parent cb38031f85
commit 0c0e1849ae
2 changed files with 40 additions and 14 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ impl<'gc> Forced<'gc> for StrictValue<'gc> {
macro_rules! impl_forced { macro_rules! impl_forced {
($($ty:ty),* $(,)?) => { ($($ty:ty),* $(,)?) => {
$( $(
impl<'gc> Forced<'gc> for <$ty as ValueVariant>::Ty<'gc> { impl<'gc> Forced<'gc> for <$ty as ValueVariant<'gc>>::Ty {
const WIDTH: usize = 1; const WIDTH: usize = 1;
#[inline(always)] #[inline(always)]
+39 -13
View File
@@ -21,12 +21,12 @@ mod private {
pub trait Cealed {} pub trait Cealed {}
} }
pub trait ValueVariant: private::Cealed { pub trait ValueVariant<'gc>: private::Cealed {
#[expect( #[expect(
private_bounds, private_bounds,
reason = "Storable is a sealed implementation detail of the value system" reason = "Storable is a sealed implementation detail of the value system"
)] )]
type Ty<'gc>: Storable + 'gc; type Ty: Storable + 'gc;
const TYPE: NixType; const TYPE: NixType;
} }
@@ -64,10 +64,20 @@ macro_rules! define_value_types {
} }
} }
impl private::Cealed for $itype {} impl private::Cealed for $itype {}
impl ValueVariant for $itype { impl<'gc> ValueVariant<'gc> for $itype {
type Ty<'gc> = $itype; type Ty = $itype;
const TYPE: NixType = $ity; const TYPE: NixType = $ity;
} }
impl<'gc> TryFrom<Value<'gc>> for $itype {
type Error = ();
fn try_from(val: Value<'gc>) -> Result<Self, Self::Error> {
<Self as Storable>::is(&val.raw)
// SAFETY: `is` returned true, so `val.raw` represents a
// valid `Self` of this GC type.
.then(|| unsafe { <Self as Storable>::from_raw_box(val.raw) })
.ok_or(())
}
}
)* )*
$( $(
impl Storable for Gc<'_, $gtype> { impl Storable for Gc<'_, $gtype> {
@@ -88,10 +98,20 @@ macro_rules! define_value_types {
unsafe { Gc::from_ptr(<*mut $gtype as RawStore>::from_val(raw.value().unwrap_unchecked())) } unsafe { Gc::from_ptr(<*mut $gtype as RawStore>::from_val(raw.value().unwrap_unchecked())) }
} }
} }
impl<'gc> TryFrom<Value<'gc>> for Gc<'gc, unelide_lifetimes!('gc; $gtype)> {
type Error = ();
fn try_from(val: Value<'gc>) -> Result<Self, Self::Error> {
<Self as Storable>::is(&val.raw)
// SAFETY: `is` returned true, so `val.raw` represents a
// valid `Self` of this GC type.
.then(|| unsafe { <Self as Storable>::from_raw_box(val.raw) })
.ok_or(())
}
}
impl private::Cealed for Gc<'_, $gtype> {} impl private::Cealed for Gc<'_, $gtype> {}
impl private::Cealed for $gtype {} impl private::Cealed for $gtype {}
impl ValueVariant for $gtype { impl<'gc> ValueVariant<'gc> for unelide_lifetimes!('gc; $gtype) {
type Ty<'gc> = Gc<'gc, unelide_lifetimes!('gc; $gtype)>; type Ty = Gc<'gc, unelide_lifetimes!('gc; $gtype)>;
const TYPE: NixType = $gty; const TYPE: NixType = $gty;
} }
)* )*
@@ -199,8 +219,8 @@ impl Storable for f64 {
} }
} }
impl ValueVariant for f64 { impl<'gc> ValueVariant<'gc> for f64 {
type Ty<'gc> = f64; type Ty = f64;
const TYPE: NixType = NixType::Float; const TYPE: NixType = NixType::Float;
} }
@@ -257,12 +277,12 @@ impl<'gc> Value<'gc> {
} }
#[inline] #[inline]
pub fn is<T: ValueVariant>(self) -> bool { pub fn is<T: ValueVariant<'gc>>(self) -> bool {
T::Ty::is(&self.raw) T::Ty::is(&self.raw)
} }
#[inline] #[inline]
pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'gc>> { pub fn downcast<T: ValueVariant<'gc>>(self) -> Option<T::Ty> {
self.is::<T>() self.is::<T>()
// SAFETY: `is::<T>()` returned true, so `self.raw` represents a // SAFETY: `is::<T>()` returned true, so `self.raw` represents a
// valid `T::Ty`. // valid `T::Ty`.
@@ -332,7 +352,7 @@ impl<'gc> Value<'gc> {
} }
#[inline] #[inline]
pub fn expect<T: ValueVariant>(self) -> Result<T::Ty<'gc>, NixType> { pub fn expect<T: ValueVariant<'gc>>(self) -> Result<T::Ty, NixType> {
self.downcast::<T>().ok_or_else(|| self.ty()) self.downcast::<T>().ok_or_else(|| self.ty())
} }
@@ -365,12 +385,12 @@ impl StaticValue {
} }
#[inline] #[inline]
pub fn is<T: ValueVariant>(self) -> bool { pub fn is<T: ValueVariant<'static>>(self) -> bool {
self.0.is::<T>() self.0.is::<T>()
} }
#[inline] #[inline]
pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'static>> { pub fn downcast<T: ValueVariant<'static>>(self) -> Option<T::Ty> {
self.0.downcast::<T>() self.0.downcast::<T>()
} }
@@ -696,6 +716,12 @@ impl<'gc> Deref for StrictValue<'gc> {
} }
} }
impl<'gc> From<StrictValue<'gc>> for Value<'gc> {
fn from(value: StrictValue<'gc>) -> Self {
value.0
}
}
impl fmt::Debug for StrictValue<'_> { impl fmt::Debug for StrictValue<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f) fmt::Debug::fmt(&self.0, f)