From ee83a365fc9338e2ae111aa897865acfe732219a Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:41:36 +0000 Subject: [PATCH 1/7] Maybe ... --- src/lib.rs | 14 ++--- src/ser.rs | 2 +- src/typeset.rs | 150 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3cdd206..5b5626a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,6 +128,8 @@ r#"TypeLayoutInfo { #![feature(decl_macro)] #![feature(freeze)] #![feature(offset_of_enum)] +#![feature(inline_const)] +#![feature(const_slice_from_raw_parts_mut)] // required, soon-stabilized features #![cfg_attr(not(version("1.83")), feature(const_mut_refs))] #![cfg_attr(not(version("1.82")), feature(offset_of_nested))] @@ -354,8 +356,7 @@ pub struct TypeLayoutGraph< F: Deref]> = &'a [Field<'a>], D: Deref = &'a [u8], V: Deref]> = &'a [Variant<'a, F, D>], - I: Deref> = &'a TypeLayoutInfo<'a, F, D, V>, - G: Deref = &'a [I], + G: Deref]> = &'a [TypeLayoutInfo<'a, F, D, V>], > { /// The type's fully-qualified name. #[cfg_attr(feature = "serde", serde(borrow))] @@ -475,12 +476,12 @@ impl TypeLayoutGraph<'static> { // - the HList is layout-equivalent to an array of the same length as ComputeSet::LEN // - ComputeSet::TYS provides a static non-dangling reference that we can use to produce // the data pointer for a slice - tys: unsafe { + tys: /*unsafe { core::slice::from_raw_parts( core::ptr::from_ref( as typeset::ComputeSet>::TYS).cast(), as typeset::ComputeSet>::LEN, ) - }, + }*/typeset::foo::type_layout_graph::(), } } } @@ -548,9 +549,8 @@ impl< F: Deref]> + fmt::Debug, D: Deref + fmt::Debug, V: Deref]> + fmt::Debug, - I: Deref> + fmt::Debug, - G: Deref + fmt::Debug, - > fmt::Debug for TypeLayoutGraph<'a, F, D, V, I, G> + G: Deref]> + fmt::Debug, + > fmt::Debug for TypeLayoutGraph<'a, F, D, V, G> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_fmt(format_args!("TypeLayoutGraph<{}>({:?})", self.ty, self.tys)) diff --git a/src/ser.rs b/src/ser.rs index b325a1c..ed4c127 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -257,7 +257,7 @@ impl Serialiser<'_> { let mut i = 0; while i < value.tys.len() { - self.serialise_type_layout_info(value.tys[i]); + self.serialise_type_layout_info(&value.tys[i]); i += 1; } diff --git a/src/typeset.rs b/src/typeset.rs index 9d8ac60..148b7bf 100644 --- a/src/typeset.rs +++ b/src/typeset.rs @@ -1,6 +1,141 @@ //! Helper module to compute the set of types that a type links to and expand it //! into the complete type graph. +use core::marker::Freeze; + +use crate::TypeLayout; + +const fn foo() -> &'static T { + const fn bar() -> T { + panic!() + } + + &const { bar::() } +} + +pub mod foo { + use core::{marker::Freeze, mem::MaybeUninit, ops::Deref}; + + use crate::{Field, TypeLayout, TypeLayoutInfo, Variant}; + + use super::{ComputeSet, ComputeTypeSet, ExpandTypeSet, private::{Cons, Empty}}; + + struct Node< + 'a, + 'b, + F: Deref]> = &'a [Field<'a>], + D: Deref = &'a [u8], + V: Deref]> = &'a [Variant<'a, F, D>], + > { + ty: TypeLayoutInfo<'a, F, D, V>, + next: Option<&'b Self>, + } + + trait HList: 'static + Copy + Freeze { + const LEN: usize; + } + + impl HList for Empty { + const LEN: usize = 0; + } + + impl HList for Cons { + const LEN: usize = 1 + T::LEN; + } + + const fn str_eq(a: &str, b: &str) -> bool { + if a.len() != b.len() { + return false; + } + + let (a, b) = (a.as_bytes(), b.as_bytes()); + + let mut i = 0; + + while i < a.len() { + if a[i] != b[i] { + return false; + } + + i += 1; + } + + true + } + + pub const fn type_layout_graph() -> &'static [TypeLayoutInfo<'static>] { + expand_type_layout_graph::(None) + } + + const fn expand_type_layout_graph(tys: Option<&Node>) -> &'static [TypeLayoutInfo<'static>] { + const fn fill_type_layout_graph() -> &'static [TypeLayoutInfo<'static>] { + const fn fill_type_layout_graph_erased() -> G { + const fn expand_type_layout_graph_erased(tys: &mut [MaybeUninit>], tys_len: usize) -> usize { + let info = T::TYPE_LAYOUT; + let mut i = 0; + while i < tys_len { + if str_eq(unsafe { tys[i].assume_init_ref() }.name, info.name) { + if S::IS_EMPTY { + return tys_len; + } + return expand_type_layout_graph_erased::(tys, tys_len); + } + i += 1; + } + if tys_len >= tys.len() { + panic!("bug: type layout graph too small"); + } + tys[tys_len] = MaybeUninit::new(info); + if as ExpandTypeSet>::IS_EMPTY { + return tys_len + 1; + } + expand_type_layout_graph_erased::< as ComputeSet>::Head, as ComputeSet>::Tail>(tys, tys_len + 1) + } + + let mut graph = MaybeUninit::::uninit(); + + let graph_slice = unsafe { core::slice::from_raw_parts_mut(core::ptr::from_mut(&mut graph).cast(), G::LEN) }; + let graph_len = expand_type_layout_graph_erased::(graph_slice, 0); + + if graph_len != G::LEN { + panic!("bug: initialized graph has the wrong size"); + } + + unsafe { graph.assume_init() } + } + + const fn fill_type_layout_graph_erased_reference() -> &'static G { + &const { fill_type_layout_graph_erased::() } + } + + unsafe { core::slice::from_raw_parts(core::ptr::from_ref(const { + fill_type_layout_graph_erased_reference::() + }).cast(), G::LEN) } + } + + let info = T::TYPE_LAYOUT; + let mut it = &tys; + while let Some(i) = it { + if str_eq(i.ty.name, info.name) { + if S::IS_EMPTY { + return fill_type_layout_graph::(); + } + return expand_type_layout_graph::(tys); + } + + it = &i.next; + } + let mut cons = Node { + ty: info, + next: tys, + }; + if as ExpandTypeSet>::IS_EMPTY { + return fill_type_layout_graph::, G>>(); + } + expand_type_layout_graph::, G>, as ComputeSet>::Head, as ComputeSet>::Tail>(Some(&mut cons)) + } +} + #[doc(hidden)] pub trait ComputeSet: sealed::ComputeSet { const LEN: usize; @@ -8,6 +143,9 @@ pub trait ComputeSet: sealed::ComputeSet { type Output: ExpandTypeSet; + type Head: ComputeTypeSet; + type Tail: ExpandTypeSet; + type TyHList: 'static + Copy + core::marker::Freeze; const TYS: &'static Self::TyHList; } @@ -106,14 +244,20 @@ pub macro tset { #[doc(hidden)] pub trait ExpandTypeSet: ComputeSet { + const IS_EMPTY: bool; + type Output: ExpandTypeSet; } impl ExpandTypeSet for private::Empty { + const IS_EMPTY: bool = true; + type Output = T; } impl ExpandTypeSet for private::Cons { + const IS_EMPTY: bool = false; + type Output = ::Output::Output>>; } @@ -148,6 +292,9 @@ mod private { type Output = Cons; type TyHList = Self; + type Head = !; // FIXME + type Tail = Self; + const LEN: usize = 0; const TYS: &'static Self::TyHList = &Self; } @@ -157,6 +304,9 @@ mod private { type Output = >::Output; type TyHList = Cons<&'static crate::TypeLayoutInfo<'static>, T::TyHList>; + type Head = H2; + type Tail = T; + const LEN: usize = T::LEN + 1; const TYS: &'static Self::TyHList = &Cons { head: &H2::TYPE_LAYOUT, From ef136cb78e172f3067cfd4cce3673a254db37743 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Mon, 25 Nov 2024 17:43:08 +0000 Subject: [PATCH 2/7] Small fix --- src/typeset.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/typeset.rs b/src/typeset.rs index 148b7bf..536d549 100644 --- a/src/typeset.rs +++ b/src/typeset.rs @@ -292,7 +292,7 @@ mod private { type Output = Cons; type TyHList = Self; - type Head = !; // FIXME + type Head = (); // FIXME type Tail = Self; const LEN: usize = 0; From 65ce7593b74561c7d06e990e02268cbdb85ca4d6 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:14:50 +0000 Subject: [PATCH 3/7] Started cleanup --- const-type-layout-derive/src/lib.rs | 2 +- src/impls/core/array.rs | 4 +- src/impls/core/cell.rs | 11 +- src/impls/core/cmp.rs | 6 +- src/impls/core/convert.rs | 4 +- src/impls/core/ffi.rs | 4 +- src/impls/core/fn.rs | 6 +- src/impls/core/marker.rs | 6 +- src/impls/core/mem.rs | 8 +- src/impls/core/num.rs | 8 +- src/impls/core/ops.rs | 16 +- src/impls/core/option.rs | 4 +- src/impls/core/pin.rs | 4 +- src/impls/core/primitive.rs | 6 +- src/impls/core/ptr.rs | 8 +- src/impls/core/ref.rs | 6 +- src/impls/core/result.rs | 4 +- src/impls/core/sync/atomic.rs | 8 +- src/impls/core/sync/mod.rs | 4 +- src/impls/core/tuple.rs | 4 +- src/lib.rs | 25 +- src/typeset.rs | 342 +++++++++++----------------- 22 files changed, 200 insertions(+), 290 deletions(-) diff --git a/const-type-layout-derive/src/lib.rs b/const-type-layout-derive/src/lib.rs index 53858bf..1efcdc9 100644 --- a/const-type-layout-derive/src/lib.rs +++ b/const-type-layout-derive/src/lib.rs @@ -114,7 +114,7 @@ pub fn derive_type_layout(input: TokenStream) -> TokenStream { unsafe impl #type_set_impl_generics #crate_path::typeset::ComputeTypeSet for #ty_name #type_set_ty_generics #type_set_where_clause { - type Output<__TypeSetRest: #crate_path::typeset::ExpandTypeSet> = + type Output<__TypeSetRest: #crate_path::typeset::ExpandTypeHList> = #crate_path::typeset::tset![ #(#inner_types,)* #discriminant_ty .. @ __TypeSetRest ]; diff --git a/src/impls/core/array.rs b/src/impls/core/array.rs index f29092d..08a44e9 100644 --- a/src/impls/core/array.rs +++ b/src/impls/core/array.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -14,5 +14,5 @@ unsafe impl TypeLayout for [T; N] { } unsafe impl ComputeTypeSet for [T; N] { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } diff --git a/src/impls/core/cell.rs b/src/impls/core/cell.rs index aed83df..727a329 100644 --- a/src/impls/core/cell.rs +++ b/src/impls/core/cell.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -21,7 +21,7 @@ unsafe impl TypeLayout for core::cell::UnsafeCell { } unsafe impl ComputeTypeSet for core::cell::UnsafeCell { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } unsafe impl TypeLayout for core::cell::Cell { @@ -42,7 +42,7 @@ unsafe impl TypeLayout for core::cell::Cell { } unsafe impl ComputeTypeSet for core::cell::Cell { - type Output = tset![core::cell::UnsafeCell, .. @ R]; + type Output = tset![core::cell::UnsafeCell, .. @ R]; } #[cfg(feature = "impl-sync-unsafe-cell")] @@ -65,7 +65,7 @@ unsafe impl TypeLayout for core::cell::SyncUnsafeCell { #[cfg(feature = "impl-sync-unsafe-cell")] unsafe impl ComputeTypeSet for core::cell::SyncUnsafeCell { - type Output = tset![core::cell::UnsafeCell, .. @ R]; + type Output = tset![core::cell::UnsafeCell, .. @ R]; } unsafe impl TypeLayout for core::cell::OnceCell { @@ -86,5 +86,6 @@ unsafe impl TypeLayout for core::cell::OnceCell { } unsafe impl ComputeTypeSet for core::cell::OnceCell { - type Output = tset![core::cell::UnsafeCell>, .. @ R]; + type Output = + tset![core::cell::UnsafeCell>, .. @ R]; } diff --git a/src/impls/core/cmp.rs b/src/impls/core/cmp.rs index dd35acf..7756e10 100644 --- a/src/impls/core/cmp.rs +++ b/src/impls/core/cmp.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; @@ -21,7 +21,7 @@ unsafe impl TypeLayout for core::cmp::Reverse { } unsafe impl ComputeTypeSet for core::cmp::Reverse { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } unsafe impl TypeLayout for core::cmp::Ordering { @@ -54,7 +54,7 @@ unsafe impl TypeLayout for core::cmp::Ordering { } unsafe impl ComputeTypeSet for core::cmp::Ordering { - type Output = tset![ + type Output = tset![ ::core::mem::Discriminant, .. @ R ]; } diff --git a/src/impls/core/convert.rs b/src/impls/core/convert.rs index 1897d92..aba4198 100644 --- a/src/impls/core/convert.rs +++ b/src/impls/core/convert.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -17,5 +17,5 @@ unsafe impl TypeLayout for core::convert::Infallible { } unsafe impl ComputeTypeSet for core::convert::Infallible { - type Output = tset![.. @ T]; + type Output = tset![.. @ T]; } diff --git a/src/impls/core/ffi.rs b/src/impls/core/ffi.rs index 1c09ddf..02312a2 100644 --- a/src/impls/core/ffi.rs +++ b/src/impls/core/ffi.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -17,5 +17,5 @@ unsafe impl TypeLayout for core::ffi::c_void { } unsafe impl ComputeTypeSet for core::ffi::c_void { - type Output = tset![.. @ T]; + type Output = tset![.. @ T]; } diff --git a/src/impls/core/fn.rs b/src/impls/core/fn.rs index cf5890a..9bdb64e 100644 --- a/src/impls/core/fn.rs +++ b/src/impls/core/fn.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -31,7 +31,7 @@ macro_rules! impl_fn_pointer_type_layout { } unsafe impl<$R: ComputeTypeSet, $($T: ComputeTypeSet),*> ComputeTypeSet for $ty { - type Output = tset![$R $(, $T)*, .. @ Z]; + type Output = tset![$R $(, $T)*, .. @ Z]; } }; ($(fn($($T:ident),*) -> $R:ident),*) => { @@ -76,7 +76,7 @@ macro_rules! impl_variadic_extern_fn_pointer_type_layout { unsafe impl<$R: ComputeTypeSet, $($T: ComputeTypeSet),*> ComputeTypeSet for unsafe extern $abi fn($($T),*, ...) -> $R { - type Output = tset![$R $(, $T)*, .. @ Z]; + type Output = tset![$R $(, $T)*, .. @ Z]; } }; ($(unsafe extern "C" fn($($T:ident),+, ...) -> $R:ident),*) => { diff --git a/src/impls/core/marker.rs b/src/impls/core/marker.rs index 05b1bd9..aa40815 100644 --- a/src/impls/core/marker.rs +++ b/src/impls/core/marker.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -17,7 +17,7 @@ unsafe impl TypeLayout for core::marker::PhantomData { } unsafe impl ComputeTypeSet for core::marker::PhantomData { - type Output = tset![.. @ R]; + type Output = tset![.. @ R]; } unsafe impl TypeLayout for core::marker::PhantomPinned { @@ -34,5 +34,5 @@ unsafe impl TypeLayout for core::marker::PhantomPinned { } unsafe impl ComputeTypeSet for core::marker::PhantomPinned { - type Output = tset![.. @ T]; + type Output = tset![.. @ T]; } diff --git a/src/impls/core/mem.rs b/src/impls/core/mem.rs index d57104a..d9ed7dc 100644 --- a/src/impls/core/mem.rs +++ b/src/impls/core/mem.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -21,7 +21,7 @@ unsafe impl TypeLayout for core::mem::ManuallyDrop { } unsafe impl ComputeTypeSet for core::mem::ManuallyDrop { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } unsafe impl TypeLayout for core::mem::MaybeUninit { @@ -49,7 +49,7 @@ unsafe impl TypeLayout for core::mem::MaybeUninit { } unsafe impl ComputeTypeSet for core::mem::MaybeUninit { - type Output = tset![(), core::mem::ManuallyDrop, .. @ R]; + type Output = tset![(), core::mem::ManuallyDrop, .. @ R]; } unsafe impl TypeLayout for core::mem::Discriminant { @@ -63,5 +63,5 @@ unsafe impl TypeLayout for core::mem::Discriminant { } unsafe impl ComputeTypeSet for core::mem::Discriminant { - type Output = tset![.. @ R]; + type Output = tset![.. @ R]; } diff --git a/src/impls/core/num.rs b/src/impls/core/num.rs index b6ca5d1..6e7edc7 100644 --- a/src/impls/core/num.rs +++ b/src/impls/core/num.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -26,7 +26,7 @@ macro_rules! impl_nonzero_type_layout { } unsafe impl ComputeTypeSet for core::num::$nz { - type Output = tset![$ty, .. @ T]; + type Output = tset![$ty, .. @ T]; } }; ($($nz:ident => $ty:ty),*) => { @@ -59,7 +59,7 @@ unsafe impl TypeLayout for core::num::Wrapping { } unsafe impl ComputeTypeSet for core::num::Wrapping { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } unsafe impl TypeLayout for core::num::Saturating { @@ -80,5 +80,5 @@ unsafe impl TypeLayout for core::num::Saturating { } unsafe impl ComputeTypeSet for core::num::Saturating { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } diff --git a/src/impls/core/ops.rs b/src/impls/core/ops.rs index 5038ec8..e7a9a91 100644 --- a/src/impls/core/ops.rs +++ b/src/impls/core/ops.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; @@ -28,7 +28,7 @@ unsafe impl TypeLayout for core::ops::Range { } unsafe impl ComputeTypeSet for core::ops::Range { - type Output = tset![Idx, .. @ R]; + type Output = tset![Idx, .. @ R]; } unsafe impl TypeLayout for core::ops::RangeFrom { @@ -49,7 +49,7 @@ unsafe impl TypeLayout for core::ops::RangeFrom { } unsafe impl ComputeTypeSet for core::ops::RangeFrom { - type Output = tset![Idx, .. @ R]; + type Output = tset![Idx, .. @ R]; } unsafe impl TypeLayout for core::ops::RangeFull { @@ -66,7 +66,7 @@ unsafe impl TypeLayout for core::ops::RangeFull { } unsafe impl ComputeTypeSet for core::ops::RangeFull { - type Output = tset![.. @ R]; + type Output = tset![.. @ R]; } unsafe impl TypeLayout for core::ops::RangeTo { @@ -87,7 +87,7 @@ unsafe impl TypeLayout for core::ops::RangeTo { } unsafe impl ComputeTypeSet for core::ops::RangeTo { - type Output = tset![Idx, .. @ R]; + type Output = tset![Idx, .. @ R]; } unsafe impl TypeLayout for core::ops::RangeToInclusive { @@ -108,7 +108,7 @@ unsafe impl TypeLayout for core::ops::RangeToInclusive { } unsafe impl ComputeTypeSet for core::ops::RangeToInclusive { - type Output = tset![Idx, .. @ R]; + type Output = tset![Idx, .. @ R]; } unsafe impl TypeLayout for core::ops::Bound { @@ -153,7 +153,7 @@ unsafe impl TypeLayout for core::ops::Bound { } unsafe impl ComputeTypeSet for core::ops::Bound { - type Output = tset![ + type Output = tset![ T, ::core::mem::Discriminant, .. @ R ]; } @@ -193,7 +193,7 @@ unsafe impl TypeLayout for core::ops::ControlFlow< } unsafe impl ComputeTypeSet for core::ops::ControlFlow { - type Output = tset![ + type Output = tset![ B, C, ::core::mem::Discriminant, .. @ R ]; } diff --git a/src/impls/core/option.rs b/src/impls/core/option.rs index bb47a2e..04a95a4 100644 --- a/src/impls/core/option.rs +++ b/src/impls/core/option.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; @@ -32,7 +32,7 @@ unsafe impl TypeLayout for core::option::Option { } unsafe impl ComputeTypeSet for core::option::Option { - type Output = tset![ + type Output = tset![ T, ::core::mem::Discriminant, .. @ R ]; } diff --git a/src/impls/core/pin.rs b/src/impls/core/pin.rs index 6d9ea6c..9e6398f 100644 --- a/src/impls/core/pin.rs +++ b/src/impls/core/pin.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -21,5 +21,5 @@ unsafe impl TypeLayout for core::pin::Pin { } unsafe impl ComputeTypeSet for core::pin::Pin { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } diff --git a/src/impls/core/primitive.rs b/src/impls/core/primitive.rs index 528acd0..52e394c 100644 --- a/src/impls/core/primitive.rs +++ b/src/impls/core/primitive.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -17,7 +17,7 @@ macro_rules! impl_primitive_type_layout { } unsafe impl ComputeTypeSet for $ty { - type Output = tset![.. @ T]; + type Output = tset![.. @ T]; } }; ($($ty:ty => $val:expr),*) => { @@ -45,5 +45,5 @@ unsafe impl TypeLayout for ! { #[cfg(feature = "impl-never")] unsafe impl ComputeTypeSet for ! { - type Output = tset![.. @ T]; + type Output = tset![.. @ T]; } diff --git a/src/impls/core/ptr.rs b/src/impls/core/ptr.rs index 1bf5a79..f7cf052 100644 --- a/src/impls/core/ptr.rs +++ b/src/impls/core/ptr.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -14,7 +14,7 @@ unsafe impl TypeLayout for *const T { } unsafe impl ComputeTypeSet for *const T { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } unsafe impl TypeLayout for *mut T { @@ -28,7 +28,7 @@ unsafe impl TypeLayout for *mut T { } unsafe impl ComputeTypeSet for *mut T { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } unsafe impl TypeLayout for core::ptr::NonNull { @@ -49,5 +49,5 @@ unsafe impl TypeLayout for core::ptr::NonNull { } unsafe impl ComputeTypeSet for core::ptr::NonNull { - type Output = tset![*const T, .. @ R]; + type Output = tset![*const T, .. @ R]; } diff --git a/src/impls/core/ref.rs b/src/impls/core/ref.rs index 8087752..66ab2d4 100644 --- a/src/impls/core/ref.rs +++ b/src/impls/core/ref.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -14,7 +14,7 @@ unsafe impl<'a, T: TypeLayout + 'a> TypeLayout for &'a T { } unsafe impl<'a, T: ComputeTypeSet + 'a> ComputeTypeSet for &'a T { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } unsafe impl<'a, T: TypeLayout + 'a> TypeLayout for &'a mut T { @@ -28,5 +28,5 @@ unsafe impl<'a, T: TypeLayout + 'a> TypeLayout for &'a mut T { } unsafe impl<'a, T: ComputeTypeSet + 'a> ComputeTypeSet for &'a mut T { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } diff --git a/src/impls/core/result.rs b/src/impls/core/result.rs index 3df460a..a67d5a1 100644 --- a/src/impls/core/result.rs +++ b/src/impls/core/result.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; @@ -36,7 +36,7 @@ unsafe impl TypeLayout for core::result::Result ComputeTypeSet for core::result::Result { - type Output = tset![ + type Output = tset![ T, E, ::core::mem::Discriminant, .. @ R ]; } diff --git a/src/impls/core/sync/atomic.rs b/src/impls/core/sync/atomic.rs index 037bd88..943c741 100644 --- a/src/impls/core/sync/atomic.rs +++ b/src/impls/core/sync/atomic.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -28,7 +28,7 @@ macro_rules! impl_atomic_int_layout { #[cfg(target_has_atomic_load_store = $cfg)] unsafe impl ComputeTypeSet for core::sync::atomic::$at { - type Output = tset![core::cell::UnsafeCell<$ty>, .. @ T]; + type Output = tset![core::cell::UnsafeCell<$ty>, .. @ T]; } }; ($($at:ident ( $align:literal : $cfg:literal ) => $ty:ty => $val:literal),*) => { @@ -76,7 +76,7 @@ macro_rules! impl_atomic_int_ptr_sized_layout { #[cfg(target_has_atomic_load_store = "ptr")] #[cfg(target_pointer_width = $cfg)] unsafe impl ComputeTypeSet for core::sync::atomic::$at { - type Output = tset![core::cell::UnsafeCell<$ty>, .. @ T]; + type Output = tset![core::cell::UnsafeCell<$ty>, .. @ T]; } }; ($($at:ident ( $align:literal : $cfg:literal ) => $ty:ty => $val:literal),*) => { @@ -118,7 +118,7 @@ macro_rules! impl_atomic_ptr_layout { #[cfg(target_has_atomic_load_store = "ptr")] #[cfg(target_pointer_width = $cfg)] unsafe impl ComputeTypeSet for core::sync::atomic::AtomicPtr { - type Output = tset![core::cell::UnsafeCell, .. @ R]; + type Output = tset![core::cell::UnsafeCell, .. @ R]; } }; ($(( $align:literal : $cfg:literal )),*) => { diff --git a/src/impls/core/sync/mod.rs b/src/impls/core/sync/mod.rs index 1d1748f..02e6c6b 100644 --- a/src/impls/core/sync/mod.rs +++ b/src/impls/core/sync/mod.rs @@ -1,6 +1,6 @@ #[cfg(feature = "impl-sync-exclusive")] use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -27,5 +27,5 @@ unsafe impl TypeLayout for core::sync::Exclusive { #[cfg(feature = "impl-sync-exclusive")] unsafe impl ComputeTypeSet for core::sync::Exclusive { - type Output = tset![T, .. @ R]; + type Output = tset![T, .. @ R]; } diff --git a/src/impls/core/tuple.rs b/src/impls/core/tuple.rs index 778280e..e07555a 100644 --- a/src/impls/core/tuple.rs +++ b/src/impls/core/tuple.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeSet}, + typeset::{tset, ComputeTypeSet, ExpandTypeHList}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -25,7 +25,7 @@ macro_rules! impl_tuple_type_layout { } unsafe impl<$($T: ComputeTypeSet),*> ComputeTypeSet for ($($T,)*) { - type Output = tset![$($T),*, .. @ T]; + type Output = tset![$($T),*, .. @ T]; } }; ($(($($a:tt => $T:ident),+)),*) => { diff --git a/src/lib.rs b/src/lib.rs index 5b5626a..7ef35b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,10 +128,10 @@ r#"TypeLayoutInfo { #![feature(decl_macro)] #![feature(freeze)] #![feature(offset_of_enum)] -#![feature(inline_const)] -#![feature(const_slice_from_raw_parts_mut)] // required, soon-stabilized features #![cfg_attr(not(version("1.83")), feature(const_mut_refs))] +#![cfg_attr(not(version("1.83")), feature(const_slice_from_raw_parts_mut))] +#![cfg_attr(not(version("1.79")), feature(inline_const))] #![cfg_attr(not(version("1.82")), feature(offset_of_nested))] // docs-specific features #![cfg_attr(doc, feature(doc_auto_cfg))] @@ -145,12 +145,10 @@ r#"TypeLayoutInfo { #![cfg_attr(feature = "impl-never", feature(never_type))] #![cfg_attr(feature = "impl-sync-exclusive", feature(exclusive_wrapper))] #![cfg_attr(feature = "impl-sync-unsafe-cell", feature(sync_unsafe_cell))] -// required INCOMPLETE features -#![allow(incomplete_features)] -#![feature(specialization)] // optional feature-gated INCOMPLETE features #![cfg_attr( feature = "serialize-to-generic-const-array", + allow(incomplete_features), feature(generic_const_exprs) )] // further crate attributes @@ -265,7 +263,7 @@ impl Default for MaybeUninhabited { /// # Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, /// # }; /// # use const_type_layout::inhabited; -/// # use const_type_layout::typeset::{ComputeTypeSet, ExpandTypeSet, tset}; +/// # use const_type_layout::typeset::{ComputeTypeSet, ExpandTypeHList, tset}; /// struct Foo { /// a: u8, /// b: u16, @@ -468,20 +466,7 @@ impl TypeLayoutGraph<'static> { pub const fn new() -> Self { Self { ty: ::TYPE_LAYOUT.name, - // SAFETY: - // - ComputeSet is a sealed trait and its TYS const is always a HList made of only Cons - // of &'static TypeLayoutInfo and Empty - // - Cons is a repr(C) struct with a head followed by a tail, Empty is a zero-sized - // repr(C) struct - // - the HList is layout-equivalent to an array of the same length as ComputeSet::LEN - // - ComputeSet::TYS provides a static non-dangling reference that we can use to produce - // the data pointer for a slice - tys: /*unsafe { - core::slice::from_raw_parts( - core::ptr::from_ref( as typeset::ComputeSet>::TYS).cast(), - as typeset::ComputeSet>::LEN, - ) - }*/typeset::foo::type_layout_graph::(), + tys: typeset::type_layout_graph::(), } } } diff --git a/src/typeset.rs b/src/typeset.rs index 536d549..6e12229 100644 --- a/src/typeset.rs +++ b/src/typeset.rs @@ -1,164 +1,141 @@ //! Helper module to compute the set of types that a type links to and expand it //! into the complete type graph. -use core::marker::Freeze; +use core::{marker::Freeze, mem::MaybeUninit}; -use crate::TypeLayout; +use crate::{TypeLayout, TypeLayoutInfo}; -const fn foo() -> &'static T { - const fn bar() -> T { - panic!() - } - - &const { bar::() } +struct Node<'a> { + ty: TypeLayoutInfo<'static>, + next: Option<&'a Self>, } -pub mod foo { - use core::{marker::Freeze, mem::MaybeUninit, ops::Deref}; - - use crate::{Field, TypeLayout, TypeLayoutInfo, Variant}; - - use super::{ComputeSet, ComputeTypeSet, ExpandTypeSet, private::{Cons, Empty}}; - - struct Node< - 'a, - 'b, - F: Deref]> = &'a [Field<'a>], - D: Deref = &'a [u8], - V: Deref]> = &'a [Variant<'a, F, D>], - > { - ty: TypeLayoutInfo<'a, F, D, V>, - next: Option<&'b Self>, +const fn str_eq(a: &str, b: &str) -> bool { + if a.len() != b.len() { + return false; } - trait HList: 'static + Copy + Freeze { - const LEN: usize; - } - - impl HList for Empty { - const LEN: usize = 0; - } + let (a, b) = (a.as_bytes(), b.as_bytes()); - impl HList for Cons { - const LEN: usize = 1 + T::LEN; - } + let mut i = 0; - const fn str_eq(a: &str, b: &str) -> bool { - if a.len() != b.len() { + while i < a.len() { + if a[i] != b[i] { return false; } - let (a, b) = (a.as_bytes(), b.as_bytes()); - - let mut i = 0; - - while i < a.len() { - if a[i] != b[i] { - return false; - } - - i += 1; - } - - true + i += 1; } - pub const fn type_layout_graph() -> &'static [TypeLayoutInfo<'static>] { - expand_type_layout_graph::(None) - } + true +} + +#[must_use] +pub const fn type_layout_graph( +) -> &'static [TypeLayoutInfo<'static>] { + expand_type_layout_graph::(None) +} - const fn expand_type_layout_graph(tys: Option<&Node>) -> &'static [TypeLayoutInfo<'static>] { - const fn fill_type_layout_graph() -> &'static [TypeLayoutInfo<'static>] { - const fn fill_type_layout_graph_erased() -> G { - const fn expand_type_layout_graph_erased(tys: &mut [MaybeUninit>], tys_len: usize) -> usize { - let info = T::TYPE_LAYOUT; - let mut i = 0; - while i < tys_len { - if str_eq(unsafe { tys[i].assume_init_ref() }.name, info.name) { - if S::IS_EMPTY { - return tys_len; - } - return expand_type_layout_graph_erased::(tys, tys_len); +const fn expand_type_layout_graph< + A: TypeLayout + ComputeTypeSet, + G: 'static + Copy + Freeze + private::HList, + T: ComputeTypeSet, + S: ExpandTypeHList, +>( + tys: Option<&Node>, +) -> &'static [TypeLayoutInfo<'static>] { + const fn fill_type_layout_graph< + A: TypeLayout + ComputeTypeSet, + G: 'static + Copy + Freeze + private::HList, + >() -> &'static [TypeLayoutInfo<'static>] { + const fn fill_type_layout_graph_erased< + A: TypeLayout + ComputeTypeSet, + G: private::HList, + >() -> G { + const fn expand_type_layout_graph_erased( + tys: &mut [MaybeUninit>], + tys_len: usize, + ) -> usize { + let info = T::TYPE_LAYOUT; + let mut i = 0; + while i < tys_len { + if str_eq(unsafe { tys[i].assume_init_ref() }.name, info.name) { + if S::LEN == 0 { + return tys_len; } - i += 1; - } - if tys_len >= tys.len() { - panic!("bug: type layout graph too small"); - } - tys[tys_len] = MaybeUninit::new(info); - if as ExpandTypeSet>::IS_EMPTY { - return tys_len + 1; + return expand_type_layout_graph_erased::(tys, tys_len); } - expand_type_layout_graph_erased::< as ComputeSet>::Head, as ComputeSet>::Tail>(tys, tys_len + 1) + i += 1; } + if tys_len >= tys.len() { + panic!("bug: type layout graph too small"); + } + tys[tys_len] = MaybeUninit::new(info); + if as private::HList>::LEN == 0 { + return tys_len + 1; + } + expand_type_layout_graph_erased::< + as private::TypeHList>::Head, + as private::TypeHList>::Tail, + >(tys, tys_len + 1) + } - let mut graph = MaybeUninit::::uninit(); - - let graph_slice = unsafe { core::slice::from_raw_parts_mut(core::ptr::from_mut(&mut graph).cast(), G::LEN) }; - let graph_len = expand_type_layout_graph_erased::(graph_slice, 0); + let mut graph = MaybeUninit::::uninit(); - if graph_len != G::LEN { - panic!("bug: initialized graph has the wrong size"); - } + let graph_slice = unsafe { + core::slice::from_raw_parts_mut(core::ptr::from_mut(&mut graph).cast(), G::LEN) + }; + let graph_len = expand_type_layout_graph_erased::(graph_slice, 0); - unsafe { graph.assume_init() } - } - - const fn fill_type_layout_graph_erased_reference() -> &'static G { - &const { fill_type_layout_graph_erased::() } + if graph_len != G::LEN { + panic!("bug: initialized graph has the wrong size"); } - unsafe { core::slice::from_raw_parts(core::ptr::from_ref(const { - fill_type_layout_graph_erased_reference::() - }).cast(), G::LEN) } + unsafe { graph.assume_init() } } - let info = T::TYPE_LAYOUT; - let mut it = &tys; - while let Some(i) = it { - if str_eq(i.ty.name, info.name) { - if S::IS_EMPTY { - return fill_type_layout_graph::(); - } - return expand_type_layout_graph::(tys); - } - - it = &i.next; + const fn fill_type_layout_graph_erased_reference< + A: TypeLayout + ComputeTypeSet, + G: 'static + Copy + Freeze + private::HList, + >() -> &'static G { + &const { fill_type_layout_graph_erased::() } } - let mut cons = Node { - ty: info, - next: tys, - }; - if as ExpandTypeSet>::IS_EMPTY { - return fill_type_layout_graph::, G>>(); + + unsafe { + core::slice::from_raw_parts( + core::ptr::from_ref(const { fill_type_layout_graph_erased_reference::() }) + .cast(), + G::LEN, + ) } - expand_type_layout_graph::, G>, as ComputeSet>::Head, as ComputeSet>::Tail>(Some(&mut cons)) } -} - -#[doc(hidden)] -pub trait ComputeSet: sealed::ComputeSet { - const LEN: usize; - type Len; - - type Output: ExpandTypeSet; - type Head: ComputeTypeSet; - type Tail: ExpandTypeSet; - - type TyHList: 'static + Copy + core::marker::Freeze; - const TYS: &'static Self::TyHList; -} - -mod sealed { - pub trait ComputeSet {} + let info = T::TYPE_LAYOUT; + let mut it = &tys; + while let Some(i) = it { + if str_eq(i.ty.name, info.name) { + if S::LEN == 0 { + return fill_type_layout_graph::(); + } + return expand_type_layout_graph::(tys); + } - impl ComputeSet for super::private::Empty {} - impl ComputeSet for super::private::Cons {} + it = &i.next; + } + if as private::HList>::LEN == 0 { + return fill_type_layout_graph::, G>>(); + } + expand_type_layout_graph::< + A, + private::Cons, G>, + as private::TypeHList>::Head, + as private::TypeHList>::Tail, + >(Some(&Node { + ty: info, + next: tys, + })) } -type Set = ::Output; - /// Computes the set of types that a type links to. /// /// # Safety @@ -178,7 +155,7 @@ type Set = ::Output; /// # Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, /// # }; /// # use const_type_layout::inhabited; -/// # use const_type_layout::typeset::{ComputeTypeSet, ExpandTypeSet, tset}; +/// # use const_type_layout::typeset::{ComputeTypeSet, ExpandTypeHList, tset}; /// struct Foo { /// a: u8, /// b: u16, @@ -210,7 +187,7 @@ type Set = ::Output; /// # } /// /// unsafe impl ComputeTypeSet for Foo { -/// type Output = tset![u8, u16]; +/// type Output = tset![u8, u16]; /// } /// ``` /// @@ -223,7 +200,7 @@ pub unsafe trait ComputeTypeSet: crate::TypeLayout { /// Enums implementing [`crate::TypeLayout`] and [`ComputeTypeSet`] /// manually should include [`core::mem::Discriminant`] in /// their [`ComputeTypeSet::Output`] using the [`tset`] helper macro. - type Output: ExpandTypeSet; + type Output: ExpandTypeHList; } /// Helper macro to expand a list of types, e.g. `H, R1, R2`, and an optional @@ -235,46 +212,29 @@ pub macro tset { () => { private::Empty }, (.. @ $T:tt) => { $T }, ($H:ty $(, $R:ty)*) => { - Set<$H, tset![$($R),*]> + private::Cons<$H, tset![$($R),*]> }, ($H:ty, $($R:ty,)* .. @ $T:ty ) => { - Set<$H, tset![$($R,)* .. @ $T]> + private::Cons<$H, tset![$($R,)* .. @ $T]> }, } #[doc(hidden)] -pub trait ExpandTypeSet: ComputeSet { - const IS_EMPTY: bool; - - type Output: ExpandTypeSet; -} - -impl ExpandTypeSet for private::Empty { - const IS_EMPTY: bool = true; - - type Output = T; -} - -impl ExpandTypeSet for private::Cons { - const IS_EMPTY: bool = false; - - type Output = - ::Output::Output>>; +pub trait ExpandTypeHList: private::TypeHList { + type Output: ExpandTypeHList; } -#[doc(hidden)] -pub trait TypeSetFixedPoint: ExpandTypeSet { - type Output: ExpandTypeSet; +impl ExpandTypeHList for private::Empty { + type Output = T; } -impl TypeSetFixedPoint for T { - type Output = ::Output, - >>::Output; +impl ExpandTypeHList for private::Cons { + type Output = + ::Output::Output>>; } mod private { - use super::{sealed, ComputeSet, ComputeTypeSet, ExpandTypeSet, Set}; + use super::{ComputeTypeSet, ExpandTypeHList}; #[repr(C)] #[derive(Copy, Clone)] @@ -287,67 +247,31 @@ mod private { tail: T, } - impl ComputeSet for Empty { - type Len = Self; - type Output = Cons; - type TyHList = Self; - - type Head = (); // FIXME - type Tail = Self; - - const LEN: usize = 0; - const TYS: &'static Self::TyHList = &Self; - } - - impl ComputeSet for Cons { - type Len = Cons<(), T::Len>; - type Output = >::Output; - type TyHList = Cons<&'static crate::TypeLayoutInfo<'static>, T::TyHList>; - - type Head = H2; - type Tail = T; - - const LEN: usize = T::LEN + 1; - const TYS: &'static Self::TyHList = &Cons { - head: &H2::TYPE_LAYOUT, - tail: *T::TYS, - }; - } - - pub trait ComputeCons: sealed::ComputeSet { - type Output: ExpandTypeSet; - } - - impl ComputeCons for Empty { - type Output = Cons; + pub trait HList { + const LEN: usize; } - impl ComputeCons for Cons { - type Output = Self; + impl HList for Empty { + const LEN: usize = 0; } - impl ComputeCons

for Cons { - default type Output = Cons>; + impl HList for Cons { + const LEN: usize = 1 + T::LEN; } - pub trait ComputeTypeSetFixedPoint: ExpandTypeSet { - type Output: ExpandTypeSet; + pub trait TypeHList: HList { + type Head: ComputeTypeSet; + type Tail: ExpandTypeHList; } - trait Same {} - impl Same for T {} - - impl ComputeTypeSetFixedPoint for T - where - T::Len: Same, - { - type Output = Self; + impl TypeHList for Empty { + // Empty's head can be anything since we never use it + type Head = (); + type Tail = Self; } - impl ComputeTypeSetFixedPoint for T { - default type Output = ::Output>>::Output; + impl TypeHList for Cons { + type Head = H2; + type Tail = T; } } - -pub(super) type TypeSet = - ::Output> as TypeSetFixedPoint>::Output; From abfc2972cbcec2644728c59482bcdd25c4399b97 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:44:32 +0000 Subject: [PATCH 4/7] Backup of refactoring progress --- src/impls/core/result.rs | 6 +-- src/impls/core/tuple.rs | 4 +- src/typeset.rs | 95 ++++++++-------------------------------- 3 files changed, 23 insertions(+), 82 deletions(-) diff --git a/src/impls/core/result.rs b/src/impls/core/result.rs index a67d5a1..10bec5c 100644 --- a/src/impls/core/result.rs +++ b/src/impls/core/result.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, + typeset::{tset, ComputeTypeSet}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; @@ -36,7 +36,7 @@ unsafe impl TypeLayout for core::result::Result ComputeTypeSet for core::result::Result { - type Output = tset![ - T, E, ::core::mem::Discriminant, .. @ R + type Output = tset![ + T, E, ::core::mem::Discriminant ]; } diff --git a/src/impls/core/tuple.rs b/src/impls/core/tuple.rs index e07555a..59f4465 100644 --- a/src/impls/core/tuple.rs +++ b/src/impls/core/tuple.rs @@ -1,5 +1,5 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, + typeset::{tset, ComputeTypeSet}, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, }; @@ -25,7 +25,7 @@ macro_rules! impl_tuple_type_layout { } unsafe impl<$($T: ComputeTypeSet),*> ComputeTypeSet for ($($T,)*) { - type Output = tset![$($T),*, .. @ T]; + type Output = tset![$($T),*]; } }; ($(($($a:tt => $T:ident),+)),*) => { diff --git a/src/typeset.rs b/src/typeset.rs index 6e12229..98c1f4c 100644 --- a/src/typeset.rs +++ b/src/typeset.rs @@ -1,6 +1,8 @@ //! Helper module to compute the set of types that a type links to and expand it //! into the complete type graph. +#![allow(missing_docs)] // FIXME + use core::{marker::Freeze, mem::MaybeUninit}; use crate::{TypeLayout, TypeLayoutInfo}; @@ -71,12 +73,12 @@ const fn expand_type_layout_graph< panic!("bug: type layout graph too small"); } tys[tys_len] = MaybeUninit::new(info); - if as private::HList>::LEN == 0 { + if <::Concat as private::HList>::LEN == 0 { return tys_len + 1; } expand_type_layout_graph_erased::< - as private::TypeHList>::Head, - as private::TypeHList>::Tail, + <::Concat as private::TypeHList>::Head, + <::Concat as private::TypeHList>::Tail, >(tys, tys_len + 1) } @@ -122,85 +124,22 @@ const fn expand_type_layout_graph< it = &i.next; } - if as private::HList>::LEN == 0 { + if <::Concat as private::HList>::LEN == 0 { return fill_type_layout_graph::, G>>(); } expand_type_layout_graph::< A, private::Cons, G>, - as private::TypeHList>::Head, - as private::TypeHList>::Tail, + <::Concat as private::TypeHList>::Head, + <::Concat as private::TypeHList>::Tail, >(Some(&Node { ty: info, next: tys, })) } -/// Computes the set of types that a type links to. -/// -/// # Safety -/// -/// It is only safe to implement this trait if it accurately includes -/// all inner component types that are referenced by this type's layout. Use -/// [`#[derive(TypeLayout)]`](const_type_layout_derive::TypeLayout) instead. -/// -/// # Example -/// -/// The struct `Foo` with `u8` and `u16` fields links to `u8` and `u16`: -/// -/// ```rust -/// # #![feature(const_type_name)] -/// # #![feature(offset_of)] -/// # use const_type_layout::{ -/// # Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -/// # }; -/// # use const_type_layout::inhabited; -/// # use const_type_layout::typeset::{ComputeTypeSet, ExpandTypeHList, tset}; -/// struct Foo { -/// a: u8, -/// b: u16, -/// } -/// -/// # unsafe impl TypeLayout for Foo { -/// # const INHABITED: MaybeUninhabited = inhabited::all![u8, u16]; -/// # -/// # const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { -/// # name: ::core::any::type_name::(), -/// # size: ::core::mem::size_of::(), -/// # alignment: ::core::mem::align_of::(), -/// # structure: TypeStructure::Struct { -/// # repr: "", -/// # fields: &[ -/// # Field { -/// # name: "a", -/// # offset: MaybeUninhabited::new::(::core::mem::offset_of!(Self, a)), -/// # ty: ::core::any::type_name::(), -/// # }, -/// # Field { -/// # name: "b", -/// # offset: MaybeUninhabited::new::(::core::mem::offset_of!(Self, b)), -/// # ty: ::core::any::type_name::(), -/// # }, -/// # ], -/// # }, -/// # }; -/// # } -/// -/// unsafe impl ComputeTypeSet for Foo { -/// type Output = tset![u8, u16]; -/// } -/// ``` -/// -/// Note that to you implement [`ComputeTypeSet`] you must also implement -/// [`crate::TypeLayout`] for it. pub unsafe trait ComputeTypeSet: crate::TypeLayout { - /// Extend the set `T` into a (larger) set containing also the types this - /// type links to. - /// - /// Enums implementing [`crate::TypeLayout`] and [`ComputeTypeSet`] - /// manually should include [`core::mem::Discriminant`] in - /// their [`ComputeTypeSet::Output`] using the [`tset`] helper macro. - type Output: ExpandTypeHList; + type Output: ExpandTypeHList; } /// Helper macro to expand a list of types, e.g. `H, R1, R2`, and an optional @@ -210,13 +149,9 @@ pub unsafe trait ComputeTypeSet: crate::TypeLayout { /// associated type to specify the list of types a type links to. pub macro tset { () => { private::Empty }, - (.. @ $T:tt) => { $T }, ($H:ty $(, $R:ty)*) => { private::Cons<$H, tset![$($R),*]> }, - ($H:ty, $($R:ty,)* .. @ $T:ty ) => { - private::Cons<$H, tset![$($R,)* .. @ $T]> - }, } #[doc(hidden)] @@ -230,7 +165,7 @@ impl ExpandTypeHList for private::Empty { impl ExpandTypeHList for private::Cons { type Output = - ::Output::Output>>; + ::Output::Output as private::TypeHList>::Concat>>; } mod private { @@ -262,16 +197,22 @@ mod private { pub trait TypeHList: HList { type Head: ComputeTypeSet; type Tail: ExpandTypeHList; + + type Concat: ExpandTypeHList; } impl TypeHList for Empty { // Empty's head can be anything since we never use it type Head = (); type Tail = Self; + + type Concat = L; } - impl TypeHList for Cons { - type Head = H2; + impl TypeHList for Cons { + type Head = H; type Tail = T; + + type Concat = Cons>; } } From 0d1c10c9346ad1a245ba5b4238a16accfdf128a0 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Tue, 26 Nov 2024 04:53:27 +0000 Subject: [PATCH 5/7] Further refactoring --- const-type-layout-derive/src/lib.rs | 58 +++-------- src/{typeset.rs => graph.rs} | 154 +++++++++++++--------------- src/impls/core/array.rs | 11 +- src/impls/core/cell.rs | 31 ++---- src/impls/core/cmp.rs | 17 +-- src/impls/core/convert.rs | 11 +- src/impls/core/ffi.rs | 11 +- src/impls/core/fn.rs | 15 +-- src/impls/core/marker.rs | 17 +-- src/impls/core/mem.rs | 23 ++--- src/impls/core/num.rs | 21 ++-- src/impls/core/ops.rs | 49 +++------ src/impls/core/option.rs | 11 +- src/impls/core/pin.rs | 11 +- src/impls/core/primitive.rs | 16 +-- src/impls/core/ptr.rs | 23 ++--- src/impls/core/ref.rs | 17 +-- src/impls/core/result.rs | 11 +- src/impls/core/sync/atomic.rs | 22 +--- src/impls/core/sync/mod.rs | 12 +-- src/impls/core/tuple.rs | 9 +- src/lib.rs | 21 ++-- 22 files changed, 187 insertions(+), 384 deletions(-) rename src/{typeset.rs => graph.rs} (56%) diff --git a/const-type-layout-derive/src/lib.rs b/const-type-layout-derive/src/lib.rs index 1efcdc9..cf2fe9d 100644 --- a/const-type-layout-derive/src/lib.rs +++ b/const-type-layout-derive/src/lib.rs @@ -78,22 +78,18 @@ pub fn derive_type_layout(input: TokenStream) -> TokenStream { let inhabited = inhabited_for_type(&crate_path, &input.data); let layout = layout_of_type(&crate_path, &ty_name, &ty_generics, &input.data, &reprs); - let inner_types = extract_inner_types(&input.data); - - let discriminant_ty = if let syn::Data::Enum(_) = input.data { - Some(quote! { ::core::mem::Discriminant, }) - } else { - None - }; - - let Generics { - type_layout_input_generics, - type_set_input_generics, - } = generate_generics(&crate_path, &input.generics, &extra_bounds, &type_params); + let mut inner_types = extract_inner_types(&input.data); + + let discriminant_ty: syn::Type; + if let syn::Data::Enum(_) = input.data { + discriminant_ty = syn::parse_quote! { ::core::mem::Discriminant }; + inner_types.push(&discriminant_ty); + } + + let type_layout_input_generics = + generate_generics(&crate_path, &input.generics, &extra_bounds, &type_params); let (type_layout_impl_generics, type_layout_ty_generics, type_layout_where_clause) = type_layout_input_generics.split_for_impl(); - let (type_set_impl_generics, type_set_ty_generics, type_set_where_clause) = - type_set_input_generics.split_for_impl(); quote! { unsafe impl #type_layout_impl_generics #crate_path::TypeLayout for @@ -109,15 +105,8 @@ pub fn derive_type_layout(input: TokenStream) -> TokenStream { structure: #layout, } }; - } - unsafe impl #type_set_impl_generics #crate_path::typeset::ComputeTypeSet for - #ty_name #type_set_ty_generics #type_set_where_clause - { - type Output<__TypeSetRest: #crate_path::typeset::ExpandTypeHList> = - #crate_path::typeset::tset![ - #(#inner_types,)* #discriminant_ty .. @ __TypeSetRest - ]; + type TypeGraphEdges = #crate_path::graph::hlist![#(#inner_types),*]; } } .into() @@ -308,19 +297,13 @@ fn extract_inner_types(data: &syn::Data) -> Vec<&syn::Type> { inner_types } -struct Generics { - type_layout_input_generics: syn::Generics, - type_set_input_generics: syn::Generics, -} - fn generate_generics( crate_path: &syn::Path, generics: &syn::Generics, extra_bounds: &[syn::WherePredicate], type_params: &[&syn::Ident], -) -> Generics { +) -> syn::Generics { let mut type_layout_input_generics = generics.clone(); - let mut type_set_input_generics = generics.clone(); for ty in type_params { type_layout_input_generics @@ -329,13 +312,6 @@ fn generate_generics( .push(syn::parse_quote! { #ty: #crate_path::TypeLayout }); - - type_set_input_generics - .make_where_clause() - .predicates - .push(syn::parse_quote! { - #ty: #crate_path::typeset::ComputeTypeSet - }); } for bound in extra_bounds { @@ -343,17 +319,9 @@ fn generate_generics( .make_where_clause() .predicates .push(bound.clone()); - - type_set_input_generics - .make_where_clause() - .predicates - .push(bound.clone()); } - Generics { - type_layout_input_generics, - type_set_input_generics, - } + type_layout_input_generics } fn layout_of_type( diff --git a/src/typeset.rs b/src/graph.rs similarity index 56% rename from src/typeset.rs rename to src/graph.rs index 98c1f4c..a61fe05 100644 --- a/src/typeset.rs +++ b/src/graph.rs @@ -1,66 +1,43 @@ -//! Helper module to compute the set of types that a type links to and expand it -//! into the complete type graph. - #![allow(missing_docs)] // FIXME use core::{marker::Freeze, mem::MaybeUninit}; use crate::{TypeLayout, TypeLayoutInfo}; -struct Node<'a> { - ty: TypeLayoutInfo<'static>, - next: Option<&'a Self>, -} - -const fn str_eq(a: &str, b: &str) -> bool { - if a.len() != b.len() { - return false; - } - - let (a, b) = (a.as_bytes(), b.as_bytes()); - - let mut i = 0; - - while i < a.len() { - if a[i] != b[i] { - return false; - } - - i += 1; - } +pub(crate) use private::TypeHList; - true +pub macro hlist { + () => { private::Empty }, + ($H:ty $(, $R:ty)*) => { + private::Cons<$H, hlist![$($R),*]> + }, } +#[allow(clippy::module_name_repetitions)] #[must_use] -pub const fn type_layout_graph( -) -> &'static [TypeLayoutInfo<'static>] { +pub const fn type_layout_graph() -> &'static [TypeLayoutInfo<'static>] { expand_type_layout_graph::(None) } const fn expand_type_layout_graph< - A: TypeLayout + ComputeTypeSet, + A: TypeLayout, G: 'static + Copy + Freeze + private::HList, - T: ComputeTypeSet, - S: ExpandTypeHList, + T: TypeLayout, + S: private::TypeHList, >( tys: Option<&Node>, ) -> &'static [TypeLayoutInfo<'static>] { - const fn fill_type_layout_graph< - A: TypeLayout + ComputeTypeSet, - G: 'static + Copy + Freeze + private::HList, - >() -> &'static [TypeLayoutInfo<'static>] { - const fn fill_type_layout_graph_erased< - A: TypeLayout + ComputeTypeSet, - G: private::HList, - >() -> G { - const fn expand_type_layout_graph_erased( + const fn fill_type_layout_graph( + ) -> &'static [TypeLayoutInfo<'static>] { + const fn fill_type_layout_graph_erased() -> G { + const fn expand_type_layout_graph_erased( tys: &mut [MaybeUninit>], tys_len: usize, ) -> usize { let info = T::TYPE_LAYOUT; let mut i = 0; while i < tys_len { + // Safety: tys has been initialized for 0..tys_len if str_eq(unsafe { tys[i].assume_init_ref() }.name, info.name) { if S::LEN == 0 { return tys_len; @@ -69,40 +46,56 @@ const fn expand_type_layout_graph< } i += 1; } - if tys_len >= tys.len() { - panic!("bug: type layout graph too small"); - } + assert!(tys_len < tys.len(), "bug: type layout graph too small"); tys[tys_len] = MaybeUninit::new(info); - if <::Concat as private::HList>::LEN == 0 { + if <::Concat as private::HList>::LEN + == 0 + { return tys_len + 1; } expand_type_layout_graph_erased::< - <::Concat as private::TypeHList>::Head, - <::Concat as private::TypeHList>::Tail, + <::Concat as private::TypeHList>::Head, + <::Concat as private::TypeHList>::Tail, >(tys, tys_len + 1) } let mut graph = MaybeUninit::::uninit(); + // SAFETY: + // - HList is a sealed trait and is constructed here to be made of only Cons of + // TypeLayoutInfo and Empty + // - Cons is a repr(C) struct with a head followed by a tail, Empty is a + // zero-sized repr(C) struct + // - the HList is layout-equivalent to an array of the same length as HList::LEN let graph_slice = unsafe { core::slice::from_raw_parts_mut(core::ptr::from_mut(&mut graph).cast(), G::LEN) }; let graph_len = expand_type_layout_graph_erased::(graph_slice, 0); - if graph_len != G::LEN { - panic!("bug: initialized graph has the wrong size"); - } + assert!( + graph_len == G::LEN, + "bug: initialized graph has the wrong size" + ); + // Safety: we have just checked that all array elements have been initialized unsafe { graph.assume_init() } } const fn fill_type_layout_graph_erased_reference< - A: TypeLayout + ComputeTypeSet, + A: TypeLayout, G: 'static + Copy + Freeze + private::HList, >() -> &'static G { &const { fill_type_layout_graph_erased::() } } + // SAFETY: + // - HList is a sealed trait and is constructed here to be made of only Cons of + // TypeLayoutInfo and Empty + // - Cons is a repr(C) struct with a head followed by a tail, Empty is a + // zero-sized repr(C) struct + // - the HList is layout-equivalent to an array of the same length as HList::LEN + // - fill_type_layout_graph_erased_reference provides a static non-dangling + // reference that we can use to produce the data pointer for a slice unsafe { core::slice::from_raw_parts( core::ptr::from_ref(const { fill_type_layout_graph_erased_reference::() }) @@ -124,52 +117,47 @@ const fn expand_type_layout_graph< it = &i.next; } - if <::Concat as private::HList>::LEN == 0 { + if <::Concat as private::HList>::LEN == 0 { return fill_type_layout_graph::, G>>(); } expand_type_layout_graph::< A, private::Cons, G>, - <::Concat as private::TypeHList>::Head, - <::Concat as private::TypeHList>::Tail, + <::Concat as private::TypeHList>::Head, + <::Concat as private::TypeHList>::Tail, >(Some(&Node { ty: info, next: tys, })) } -pub unsafe trait ComputeTypeSet: crate::TypeLayout { - type Output: ExpandTypeHList; +struct Node<'a> { + ty: TypeLayoutInfo<'static>, + next: Option<&'a Self>, } -/// Helper macro to expand a list of types, e.g. `H, R1, R2`, and an optional -/// tail, `.. @ T`, into a set of types. -/// -/// This macro is used when implementing the [`ComputeTypeSet::Output`] -/// associated type to specify the list of types a type links to. -pub macro tset { - () => { private::Empty }, - ($H:ty $(, $R:ty)*) => { - private::Cons<$H, tset![$($R),*]> - }, -} +const fn str_eq(a: &str, b: &str) -> bool { + if a.len() != b.len() { + return false; + } -#[doc(hidden)] -pub trait ExpandTypeHList: private::TypeHList { - type Output: ExpandTypeHList; -} + let (a, b) = (a.as_bytes(), b.as_bytes()); -impl ExpandTypeHList for private::Empty { - type Output = T; -} + let mut i = 0; + + while i < a.len() { + if a[i] != b[i] { + return false; + } -impl ExpandTypeHList for private::Cons { - type Output = - ::Output::Output as private::TypeHList>::Concat>>; + i += 1; + } + + true } mod private { - use super::{ComputeTypeSet, ExpandTypeHList}; + use crate::TypeLayout; #[repr(C)] #[derive(Copy, Clone)] @@ -195,24 +183,22 @@ mod private { } pub trait TypeHList: HList { - type Head: ComputeTypeSet; - type Tail: ExpandTypeHList; + type Head: TypeLayout; + type Tail: TypeHList; - type Concat: ExpandTypeHList; + type Concat: TypeHList; } impl TypeHList for Empty { + type Concat = L; // Empty's head can be anything since we never use it type Head = (); type Tail = Self; - - type Concat = L; } - impl TypeHList for Cons { + impl TypeHList for Cons { + type Concat = Cons>; type Head = H; type Tail = T; - - type Concat = Cons>; } } diff --git a/src/impls/core/array.rs b/src/impls/core/array.rs index 08a44e9..b2200b1 100644 --- a/src/impls/core/array.rs +++ b/src/impls/core/array.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for [T; N] { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -12,7 +11,3 @@ unsafe impl TypeLayout for [T; N] { structure: TypeStructure::Primitive, }; } - -unsafe impl ComputeTypeSet for [T; N] { - type Output = tset![T, .. @ R]; -} diff --git a/src/impls/core/cell.rs b/src/impls/core/cell.rs index 727a329..0f2c3d7 100644 --- a/src/impls/core/cell.rs +++ b/src/impls/core/cell.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for core::cell::UnsafeCell { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -20,11 +19,9 @@ unsafe impl TypeLayout for core::cell::UnsafeCell { }; } -unsafe impl ComputeTypeSet for core::cell::UnsafeCell { - type Output = tset![T, .. @ R]; -} - unsafe impl TypeLayout for core::cell::Cell { + type TypeGraphEdges = hlist![core::cell::UnsafeCell]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -41,12 +38,10 @@ unsafe impl TypeLayout for core::cell::Cell { }; } -unsafe impl ComputeTypeSet for core::cell::Cell { - type Output = tset![core::cell::UnsafeCell, .. @ R]; -} - #[cfg(feature = "impl-sync-unsafe-cell")] unsafe impl TypeLayout for core::cell::SyncUnsafeCell { + type TypeGraphEdges = hlist![core::cell::UnsafeCell]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -63,12 +58,9 @@ unsafe impl TypeLayout for core::cell::SyncUnsafeCell { }; } -#[cfg(feature = "impl-sync-unsafe-cell")] -unsafe impl ComputeTypeSet for core::cell::SyncUnsafeCell { - type Output = tset![core::cell::UnsafeCell, .. @ R]; -} - unsafe impl TypeLayout for core::cell::OnceCell { + type TypeGraphEdges = hlist![core::cell::UnsafeCell>]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -84,8 +76,3 @@ unsafe impl TypeLayout for core::cell::OnceCell { }, }; } - -unsafe impl ComputeTypeSet for core::cell::OnceCell { - type Output = - tset![core::cell::UnsafeCell>, .. @ R]; -} diff --git a/src/impls/core/cmp.rs b/src/impls/core/cmp.rs index 7756e10..1f1477c 100644 --- a/src/impls/core/cmp.rs +++ b/src/impls/core/cmp.rs @@ -1,9 +1,10 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, + graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; unsafe impl TypeLayout for core::cmp::Reverse { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -20,11 +21,9 @@ unsafe impl TypeLayout for core::cmp::Reverse { }; } -unsafe impl ComputeTypeSet for core::cmp::Reverse { - type Output = tset![T, .. @ R]; -} - unsafe impl TypeLayout for core::cmp::Ordering { + type TypeGraphEdges = hlist![::core::mem::Discriminant]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -52,9 +51,3 @@ unsafe impl TypeLayout for core::cmp::Ordering { }, }; } - -unsafe impl ComputeTypeSet for core::cmp::Ordering { - type Output = tset![ - ::core::mem::Discriminant, .. @ R - ]; -} diff --git a/src/impls/core/convert.rs b/src/impls/core/convert.rs index aba4198..86f3ec5 100644 --- a/src/impls/core/convert.rs +++ b/src/impls/core/convert.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for core::convert::Infallible { + type TypeGraphEdges = hlist![]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::any![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -15,7 +14,3 @@ unsafe impl TypeLayout for core::convert::Infallible { }, }; } - -unsafe impl ComputeTypeSet for core::convert::Infallible { - type Output = tset![.. @ T]; -} diff --git a/src/impls/core/ffi.rs b/src/impls/core/ffi.rs index 02312a2..d4b26aa 100644 --- a/src/impls/core/ffi.rs +++ b/src/impls/core/ffi.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for core::ffi::c_void { + type TypeGraphEdges = hlist![]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -15,7 +14,3 @@ unsafe impl TypeLayout for core::ffi::c_void { }, }; } - -unsafe impl ComputeTypeSet for core::ffi::c_void { - type Output = tset![.. @ T]; -} diff --git a/src/impls/core/fn.rs b/src/impls/core/fn.rs index 9bdb64e..6d13822 100644 --- a/src/impls/core/fn.rs +++ b/src/impls/core/fn.rs @@ -1,7 +1,4 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, TypeLayout, TypeLayoutInfo, TypeStructure}; macro_rules! impl_fn_pointer_type_layout { (impl extern $abi:literal fn($($T:ident),*) -> $R:ident) => { @@ -28,10 +25,8 @@ macro_rules! impl_fn_pointer_type_layout { alignment: ::core::mem::align_of::(), structure: TypeStructure::Primitive, }; - } - unsafe impl<$R: ComputeTypeSet, $($T: ComputeTypeSet),*> ComputeTypeSet for $ty { - type Output = tset![$R $(, $T)*, .. @ Z]; + type TypeGraphEdges = hlist![$R $(, $T)*]; } }; ($(fn($($T:ident),*) -> $R:ident),*) => { @@ -71,12 +66,8 @@ macro_rules! impl_variadic_extern_fn_pointer_type_layout { alignment: ::core::mem::align_of::(), structure: TypeStructure::Primitive, }; - } - unsafe impl<$R: ComputeTypeSet, $($T: ComputeTypeSet),*> ComputeTypeSet - for unsafe extern $abi fn($($T),*, ...) -> $R - { - type Output = tset![$R $(, $T)*, .. @ Z]; + type TypeGraphEdges = hlist![$R $(, $T)*]; } }; ($(unsafe extern "C" fn($($T:ident),+, ...) -> $R:ident),*) => { diff --git a/src/impls/core/marker.rs b/src/impls/core/marker.rs index aa40815..fcc8d3b 100644 --- a/src/impls/core/marker.rs +++ b/src/impls/core/marker.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for core::marker::PhantomData { + type TypeGraphEdges = hlist![]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -16,11 +15,9 @@ unsafe impl TypeLayout for core::marker::PhantomData { }; } -unsafe impl ComputeTypeSet for core::marker::PhantomData { - type Output = tset![.. @ R]; -} - unsafe impl TypeLayout for core::marker::PhantomPinned { + type TypeGraphEdges = hlist![]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -32,7 +29,3 @@ unsafe impl TypeLayout for core::marker::PhantomPinned { }, }; } - -unsafe impl ComputeTypeSet for core::marker::PhantomPinned { - type Output = tset![.. @ T]; -} diff --git a/src/impls/core/mem.rs b/src/impls/core/mem.rs index d9ed7dc..c528730 100644 --- a/src/impls/core/mem.rs +++ b/src/impls/core/mem.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for core::mem::ManuallyDrop { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -20,11 +19,9 @@ unsafe impl TypeLayout for core::mem::ManuallyDrop { }; } -unsafe impl ComputeTypeSet for core::mem::ManuallyDrop { - type Output = tset![T, .. @ R]; -} - unsafe impl TypeLayout for core::mem::MaybeUninit { + type TypeGraphEdges = hlist![(), core::mem::ManuallyDrop]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -48,11 +45,9 @@ unsafe impl TypeLayout for core::mem::MaybeUninit { }; } -unsafe impl ComputeTypeSet for core::mem::MaybeUninit { - type Output = tset![(), core::mem::ManuallyDrop, .. @ R]; -} - unsafe impl TypeLayout for core::mem::Discriminant { + type TypeGraphEdges = hlist![]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -61,7 +56,3 @@ unsafe impl TypeLayout for core::mem::Discriminant { structure: TypeStructure::Primitive, }; } - -unsafe impl ComputeTypeSet for core::mem::Discriminant { - type Output = tset![.. @ R]; -} diff --git a/src/impls/core/num.rs b/src/impls/core/num.rs index 6e7edc7..257073b 100644 --- a/src/impls/core/num.rs +++ b/src/impls/core/num.rs @@ -1,7 +1,4 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; macro_rules! impl_nonzero_type_layout { (impl $nz:ident => $ty:ty) => { @@ -23,10 +20,8 @@ macro_rules! impl_nonzero_type_layout { ], }, }; - } - unsafe impl ComputeTypeSet for core::num::$nz { - type Output = tset![$ty, .. @ T]; + type TypeGraphEdges = hlist![$ty]; } }; ($($nz:ident => $ty:ty),*) => { @@ -42,6 +37,8 @@ impl_nonzero_type_layout! { } unsafe impl TypeLayout for core::num::Wrapping { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -58,11 +55,9 @@ unsafe impl TypeLayout for core::num::Wrapping { }; } -unsafe impl ComputeTypeSet for core::num::Wrapping { - type Output = tset![T, .. @ R]; -} - unsafe impl TypeLayout for core::num::Saturating { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -78,7 +73,3 @@ unsafe impl TypeLayout for core::num::Saturating { }, }; } - -unsafe impl ComputeTypeSet for core::num::Saturating { - type Output = tset![T, .. @ R]; -} diff --git a/src/impls/core/ops.rs b/src/impls/core/ops.rs index e7a9a91..184712d 100644 --- a/src/impls/core/ops.rs +++ b/src/impls/core/ops.rs @@ -1,9 +1,10 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, + graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; unsafe impl TypeLayout for core::ops::Range { + type TypeGraphEdges = hlist![Idx]; + const INHABITED: crate::MaybeUninhabited = Idx::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -27,11 +28,9 @@ unsafe impl TypeLayout for core::ops::Range { }; } -unsafe impl ComputeTypeSet for core::ops::Range { - type Output = tset![Idx, .. @ R]; -} - unsafe impl TypeLayout for core::ops::RangeFrom { + type TypeGraphEdges = hlist![Idx]; + const INHABITED: crate::MaybeUninhabited = Idx::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -48,11 +47,9 @@ unsafe impl TypeLayout for core::ops::RangeFrom { }; } -unsafe impl ComputeTypeSet for core::ops::RangeFrom { - type Output = tset![Idx, .. @ R]; -} - unsafe impl TypeLayout for core::ops::RangeFull { + type TypeGraphEdges = hlist![]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -65,11 +62,9 @@ unsafe impl TypeLayout for core::ops::RangeFull { }; } -unsafe impl ComputeTypeSet for core::ops::RangeFull { - type Output = tset![.. @ R]; -} - unsafe impl TypeLayout for core::ops::RangeTo { + type TypeGraphEdges = hlist![Idx]; + const INHABITED: crate::MaybeUninhabited = Idx::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -86,11 +81,9 @@ unsafe impl TypeLayout for core::ops::RangeTo { }; } -unsafe impl ComputeTypeSet for core::ops::RangeTo { - type Output = tset![Idx, .. @ R]; -} - unsafe impl TypeLayout for core::ops::RangeToInclusive { + type TypeGraphEdges = hlist![Idx]; + const INHABITED: crate::MaybeUninhabited = Idx::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -107,11 +100,9 @@ unsafe impl TypeLayout for core::ops::RangeToInclusive { }; } -unsafe impl ComputeTypeSet for core::ops::RangeToInclusive { - type Output = tset![Idx, .. @ R]; -} - unsafe impl TypeLayout for core::ops::Bound { + type TypeGraphEdges = hlist![T, ::core::mem::Discriminant]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -152,13 +143,9 @@ unsafe impl TypeLayout for core::ops::Bound { }; } -unsafe impl ComputeTypeSet for core::ops::Bound { - type Output = tset![ - T, ::core::mem::Discriminant, .. @ R - ]; -} - unsafe impl TypeLayout for core::ops::ControlFlow { + type TypeGraphEdges = hlist![B, C, ::core::mem::Discriminant]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::any![B, C]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -191,9 +178,3 @@ unsafe impl TypeLayout for core::ops::ControlFlow< }, }; } - -unsafe impl ComputeTypeSet for core::ops::ControlFlow { - type Output = tset![ - B, C, ::core::mem::Discriminant, .. @ R - ]; -} diff --git a/src/impls/core/option.rs b/src/impls/core/option.rs index 04a95a4..6966dc6 100644 --- a/src/impls/core/option.rs +++ b/src/impls/core/option.rs @@ -1,9 +1,10 @@ use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, + graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; unsafe impl TypeLayout for core::option::Option { + type TypeGraphEdges = hlist![T, ::core::mem::Discriminant]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -30,9 +31,3 @@ unsafe impl TypeLayout for core::option::Option { }, }; } - -unsafe impl ComputeTypeSet for core::option::Option { - type Output = tset![ - T, ::core::mem::Discriminant, .. @ R - ]; -} diff --git a/src/impls/core/pin.rs b/src/impls/core/pin.rs index 9e6398f..48a5c0d 100644 --- a/src/impls/core/pin.rs +++ b/src/impls/core/pin.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for core::pin::Pin { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -19,7 +18,3 @@ unsafe impl TypeLayout for core::pin::Pin { }, }; } - -unsafe impl ComputeTypeSet for core::pin::Pin { - type Output = tset![T, .. @ R]; -} diff --git a/src/impls/core/primitive.rs b/src/impls/core/primitive.rs index 52e394c..53b7241 100644 --- a/src/impls/core/primitive.rs +++ b/src/impls/core/primitive.rs @@ -1,7 +1,4 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, TypeLayout, TypeLayoutInfo, TypeStructure}; macro_rules! impl_primitive_type_layout { (impl $ty:ty => $val:expr) => { @@ -14,10 +11,8 @@ macro_rules! impl_primitive_type_layout { alignment: ::core::mem::align_of::(), structure: TypeStructure::Primitive, }; - } - unsafe impl ComputeTypeSet for $ty { - type Output = tset![.. @ T]; + type TypeGraphEdges = hlist![]; } }; ($($ty:ty => $val:expr),*) => { @@ -34,6 +29,8 @@ impl_primitive_type_layout! { #[cfg(feature = "impl-never")] unsafe impl TypeLayout for ! { + type TypeGraphEdges = hlist![]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::any![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -42,8 +39,3 @@ unsafe impl TypeLayout for ! { structure: TypeStructure::Primitive, }; } - -#[cfg(feature = "impl-never")] -unsafe impl ComputeTypeSet for ! { - type Output = tset![.. @ T]; -} diff --git a/src/impls/core/ptr.rs b/src/impls/core/ptr.rs index f7cf052..f111cf4 100644 --- a/src/impls/core/ptr.rs +++ b/src/impls/core/ptr.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl TypeLayout for *const T { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -13,11 +12,9 @@ unsafe impl TypeLayout for *const T { }; } -unsafe impl ComputeTypeSet for *const T { - type Output = tset![T, .. @ R]; -} - unsafe impl TypeLayout for *mut T { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -27,11 +24,9 @@ unsafe impl TypeLayout for *mut T { }; } -unsafe impl ComputeTypeSet for *mut T { - type Output = tset![T, .. @ R]; -} - unsafe impl TypeLayout for core::ptr::NonNull { + type TypeGraphEdges = hlist![*const T]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -47,7 +42,3 @@ unsafe impl TypeLayout for core::ptr::NonNull { }, }; } - -unsafe impl ComputeTypeSet for core::ptr::NonNull { - type Output = tset![*const T, .. @ R]; -} diff --git a/src/impls/core/ref.rs b/src/impls/core/ref.rs index 66ab2d4..497a29f 100644 --- a/src/impls/core/ref.rs +++ b/src/impls/core/ref.rs @@ -1,9 +1,8 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, TypeLayout, TypeLayoutInfo, TypeStructure}; unsafe impl<'a, T: TypeLayout + 'a> TypeLayout for &'a T { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -13,11 +12,9 @@ unsafe impl<'a, T: TypeLayout + 'a> TypeLayout for &'a T { }; } -unsafe impl<'a, T: ComputeTypeSet + 'a> ComputeTypeSet for &'a T { - type Output = tset![T, .. @ R]; -} - unsafe impl<'a, T: TypeLayout + 'a> TypeLayout for &'a mut T { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::all![]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -26,7 +23,3 @@ unsafe impl<'a, T: TypeLayout + 'a> TypeLayout for &'a mut T { structure: TypeStructure::Primitive, }; } - -unsafe impl<'a, T: ComputeTypeSet + 'a> ComputeTypeSet for &'a mut T { - type Output = tset![T, .. @ R]; -} diff --git a/src/impls/core/result.rs b/src/impls/core/result.rs index 10bec5c..fb07d2e 100644 --- a/src/impls/core/result.rs +++ b/src/impls/core/result.rs @@ -1,9 +1,10 @@ use crate::{ - typeset::{tset, ComputeTypeSet}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, + graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, Variant, }; unsafe impl TypeLayout for core::result::Result { + type TypeGraphEdges = hlist![T, E, ::core::mem::Discriminant]; + const INHABITED: crate::MaybeUninhabited = crate::inhabited::any![T, E]; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -34,9 +35,3 @@ unsafe impl TypeLayout for core::result::Result ComputeTypeSet for core::result::Result { - type Output = tset![ - T, E, ::core::mem::Discriminant - ]; -} diff --git a/src/impls/core/sync/atomic.rs b/src/impls/core/sync/atomic.rs index 943c741..95cd46d 100644 --- a/src/impls/core/sync/atomic.rs +++ b/src/impls/core/sync/atomic.rs @@ -1,7 +1,4 @@ -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; macro_rules! impl_atomic_int_layout { (impl $at:ident ( $align:literal : $cfg:literal ) => $ty:ty => $val:literal) => { @@ -24,11 +21,8 @@ macro_rules! impl_atomic_int_layout { ], }, }; - } - #[cfg(target_has_atomic_load_store = $cfg)] - unsafe impl ComputeTypeSet for core::sync::atomic::$at { - type Output = tset![core::cell::UnsafeCell<$ty>, .. @ T]; + type TypeGraphEdges = hlist![core::cell::UnsafeCell<$ty>]; } }; ($($at:ident ( $align:literal : $cfg:literal ) => $ty:ty => $val:literal),*) => { @@ -71,12 +65,8 @@ macro_rules! impl_atomic_int_ptr_sized_layout { ], }, }; - } - #[cfg(target_has_atomic_load_store = "ptr")] - #[cfg(target_pointer_width = $cfg)] - unsafe impl ComputeTypeSet for core::sync::atomic::$at { - type Output = tset![core::cell::UnsafeCell<$ty>, .. @ T]; + type TypeGraphEdges = hlist![core::cell::UnsafeCell<$ty>]; } }; ($($at:ident ( $align:literal : $cfg:literal ) => $ty:ty => $val:literal),*) => { @@ -113,12 +103,8 @@ macro_rules! impl_atomic_ptr_layout { ], }, }; - } - #[cfg(target_has_atomic_load_store = "ptr")] - #[cfg(target_pointer_width = $cfg)] - unsafe impl ComputeTypeSet for core::sync::atomic::AtomicPtr { - type Output = tset![core::cell::UnsafeCell, .. @ R]; + type TypeGraphEdges = hlist![core::cell::UnsafeCell]; } }; ($(( $align:literal : $cfg:literal )),*) => { diff --git a/src/impls/core/sync/mod.rs b/src/impls/core/sync/mod.rs index 02e6c6b..b075d44 100644 --- a/src/impls/core/sync/mod.rs +++ b/src/impls/core/sync/mod.rs @@ -1,14 +1,13 @@ #[cfg(feature = "impl-sync-exclusive")] -use crate::{ - typeset::{tset, ComputeTypeSet, ExpandTypeHList}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; #[cfg(feature = "impl-atomics")] mod atomic; #[cfg(feature = "impl-sync-exclusive")] unsafe impl TypeLayout for core::sync::Exclusive { + type TypeGraphEdges = hlist![T]; + const INHABITED: crate::MaybeUninhabited = T::INHABITED; const TYPE_LAYOUT: TypeLayoutInfo<'static> = TypeLayoutInfo { name: ::core::any::type_name::(), @@ -24,8 +23,3 @@ unsafe impl TypeLayout for core::sync::Exclusive { }, }; } - -#[cfg(feature = "impl-sync-exclusive")] -unsafe impl ComputeTypeSet for core::sync::Exclusive { - type Output = tset![T, .. @ R]; -} diff --git a/src/impls/core/tuple.rs b/src/impls/core/tuple.rs index 59f4465..48e26df 100644 --- a/src/impls/core/tuple.rs +++ b/src/impls/core/tuple.rs @@ -1,7 +1,4 @@ -use crate::{ - typeset::{tset, ComputeTypeSet}, - Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, -}; +use crate::{graph::hlist, Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure}; macro_rules! impl_tuple_type_layout { (impl ($($a:tt => $T:ident),+)) => { @@ -22,10 +19,8 @@ macro_rules! impl_tuple_type_layout { }),*], }, }; - } - unsafe impl<$($T: ComputeTypeSet),*> ComputeTypeSet for ($($T,)*) { - type Output = tset![$($T),*]; + type TypeGraphEdges = hlist![$($T),*]; } }; ($(($($a:tt => $T:ident),+)),*) => { diff --git a/src/lib.rs b/src/lib.rs index 7ef35b2..cc6d09e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,10 +167,10 @@ use core::ops::Deref; pub use const_type_layout_derive::TypeLayout; mod discriminant; +pub mod graph; mod impls; pub mod inhabited; mod ser; -pub mod typeset; pub use discriminant::Discriminant; @@ -262,8 +262,7 @@ impl Default for MaybeUninhabited { /// # use const_type_layout::{ /// # Field, MaybeUninhabited, TypeLayout, TypeLayoutInfo, TypeStructure, /// # }; -/// # use const_type_layout::inhabited; -/// # use const_type_layout::typeset::{ComputeTypeSet, ExpandTypeHList, tset}; +/// # use const_type_layout::{graph, inhabited}; /// struct Foo { /// a: u8, /// b: u16, @@ -292,11 +291,10 @@ impl Default for MaybeUninhabited { /// ], /// }, /// }; +/// +/// type TypeGraphEdges = graph::hlist![u8, u16]; /// } /// ``` -/// -/// Note that if you implement [`TypeLayout`], you should also implement -/// [`typeset::ComputeTypeSet`] for it. pub unsafe trait TypeLayout: Sized { /// Marker for whether the type is /// [inhabited](https://doc.rust-lang.org/reference/glossary.html#inhabited) or @@ -305,15 +303,18 @@ pub unsafe trait TypeLayout: Sized { /// Shallow layout of the type. const TYPE_LAYOUT: TypeLayoutInfo<'static>; + + #[allow(missing_docs)] // FIXME + type TypeGraphEdges: graph::TypeHList; } /// Utility trait that provides the deep layout of a type. -pub trait TypeGraphLayout: TypeLayout + typeset::ComputeTypeSet { +pub trait TypeGraphLayout: TypeLayout { /// Shallow layout of the type. const TYPE_GRAPH: TypeLayoutGraph<'static>; } -impl TypeGraphLayout for T { +impl TypeGraphLayout for T { const TYPE_GRAPH: TypeLayoutGraph<'static> = TypeLayoutGraph::new::(); } @@ -463,10 +464,10 @@ pub struct Field<'a> { impl TypeLayoutGraph<'static> { #[must_use] /// Construct the deep type layout descriptor for a type `T`. - pub const fn new() -> Self { + pub const fn new() -> Self { Self { ty: ::TYPE_LAYOUT.name, - tys: typeset::type_layout_graph::(), + tys: graph::type_layout_graph::(), } } } From 373f2ba9a12c2087d55e6c00c17c14509b589af4 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:10:15 +0000 Subject: [PATCH 6/7] Add back support for TypeLayoutInfo ref slices --- src/graph.rs | 18 +++++++++--------- src/lib.rs | 8 +++++--- src/ser.rs | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index a61fe05..f936051 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -15,7 +15,7 @@ pub macro hlist { #[allow(clippy::module_name_repetitions)] #[must_use] -pub const fn type_layout_graph() -> &'static [TypeLayoutInfo<'static>] { +pub const fn type_layout_graph() -> &'static [&'static TypeLayoutInfo<'static>] { expand_type_layout_graph::(None) } @@ -26,15 +26,15 @@ const fn expand_type_layout_graph< S: private::TypeHList, >( tys: Option<&Node>, -) -> &'static [TypeLayoutInfo<'static>] { +) -> &'static [&'static TypeLayoutInfo<'static>] { const fn fill_type_layout_graph( - ) -> &'static [TypeLayoutInfo<'static>] { + ) -> &'static [&'static TypeLayoutInfo<'static>] { const fn fill_type_layout_graph_erased() -> G { const fn expand_type_layout_graph_erased( - tys: &mut [MaybeUninit>], + tys: &mut [MaybeUninit<&'static TypeLayoutInfo<'static>>], tys_len: usize, ) -> usize { - let info = T::TYPE_LAYOUT; + let info = &T::TYPE_LAYOUT; let mut i = 0; while i < tys_len { // Safety: tys has been initialized for 0..tys_len @@ -105,7 +105,7 @@ const fn expand_type_layout_graph< } } - let info = T::TYPE_LAYOUT; + let info = &T::TYPE_LAYOUT; let mut it = &tys; while let Some(i) = it { if str_eq(i.ty.name, info.name) { @@ -118,11 +118,11 @@ const fn expand_type_layout_graph< it = &i.next; } if <::Concat as private::HList>::LEN == 0 { - return fill_type_layout_graph::, G>>(); + return fill_type_layout_graph::, G>>(); } expand_type_layout_graph::< A, - private::Cons, G>, + private::Cons<&'static TypeLayoutInfo<'static>, G>, <::Concat as private::TypeHList>::Head, <::Concat as private::TypeHList>::Tail, >(Some(&Node { @@ -132,7 +132,7 @@ const fn expand_type_layout_graph< } struct Node<'a> { - ty: TypeLayoutInfo<'static>, + ty: &'static TypeLayoutInfo<'static>, next: Option<&'a Self>, } diff --git a/src/lib.rs b/src/lib.rs index cc6d09e..7ecf5e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -355,7 +355,8 @@ pub struct TypeLayoutGraph< F: Deref]> = &'a [Field<'a>], D: Deref = &'a [u8], V: Deref]> = &'a [Variant<'a, F, D>], - G: Deref]> = &'a [TypeLayoutInfo<'a, F, D, V>], + I: Deref> = &'a TypeLayoutInfo<'a, F, D, V>, + G: Deref = &'a [I], > { /// The type's fully-qualified name. #[cfg_attr(feature = "serde", serde(borrow))] @@ -535,8 +536,9 @@ impl< F: Deref]> + fmt::Debug, D: Deref + fmt::Debug, V: Deref]> + fmt::Debug, - G: Deref]> + fmt::Debug, - > fmt::Debug for TypeLayoutGraph<'a, F, D, V, G> + I: Deref> + fmt::Debug, + G: Deref + fmt::Debug, + > fmt::Debug for TypeLayoutGraph<'a, F, D, V, I, G> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_fmt(format_args!("TypeLayoutGraph<{}>({:?})", self.ty, self.tys)) diff --git a/src/ser.rs b/src/ser.rs index ed4c127..b325a1c 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -257,7 +257,7 @@ impl Serialiser<'_> { let mut i = 0; while i < value.tys.len() { - self.serialise_type_layout_info(&value.tys[i]); + self.serialise_type_layout_info(value.tys[i]); i += 1; } From e759138d2733edd203c754a81c51dd6520e50044 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Tue, 26 Nov 2024 18:59:42 +0000 Subject: [PATCH 7/7] Document the implementation of the specialisation-free type graph construction --- src/graph.rs | 268 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 170 insertions(+), 98 deletions(-) diff --git a/src/graph.rs b/src/graph.rs index f936051..56f6f26 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -16,126 +16,198 @@ pub macro hlist { #[allow(clippy::module_name_repetitions)] #[must_use] pub const fn type_layout_graph() -> &'static [&'static TypeLayoutInfo<'static>] { - expand_type_layout_graph::(None) + expand_type_layout_stack_graph_into_static_slice::(None) } -const fn expand_type_layout_graph< - A: TypeLayout, - G: 'static + Copy + Freeze + private::HList, +// compute the type graph by keeping an on-stack linked list of already-seen +// types +// as the stack graph is computed, accumulate the hlist type that is layout- +// equivalent to an array storing all of the type layouts +// once the graph is computed on the stack, recompute it inside a const using +// the now-known type of the hlist +// a static slice to the array of type layouts is returned +const fn expand_type_layout_stack_graph_into_static_slice< + GraphRoot: TypeLayout, + GraphNodesArray: 'static + Copy + Freeze + private::HList, T: TypeLayout, - S: private::TypeHList, + RemainingTypes: private::TypeHList, >( - tys: Option<&Node>, + tys: Option<&GraphStackNode>, ) -> &'static [&'static TypeLayoutInfo<'static>] { - const fn fill_type_layout_graph( - ) -> &'static [&'static TypeLayoutInfo<'static>] { - const fn fill_type_layout_graph_erased() -> G { - const fn expand_type_layout_graph_erased( - tys: &mut [MaybeUninit<&'static TypeLayoutInfo<'static>>], - tys_len: usize, - ) -> usize { - let info = &T::TYPE_LAYOUT; - let mut i = 0; - while i < tys_len { - // Safety: tys has been initialized for 0..tys_len - if str_eq(unsafe { tys[i].assume_init_ref() }.name, info.name) { - if S::LEN == 0 { - return tys_len; - } - return expand_type_layout_graph_erased::(tys, tys_len); - } - i += 1; - } - assert!(tys_len < tys.len(), "bug: type layout graph too small"); - tys[tys_len] = MaybeUninit::new(info); - if <::Concat as private::HList>::LEN - == 0 - { - return tys_len + 1; - } - expand_type_layout_graph_erased::< - <::Concat as private::TypeHList>::Head, - <::Concat as private::TypeHList>::Tail, - >(tys, tys_len + 1) - } - - let mut graph = MaybeUninit::::uninit(); - - // SAFETY: - // - HList is a sealed trait and is constructed here to be made of only Cons of - // TypeLayoutInfo and Empty - // - Cons is a repr(C) struct with a head followed by a tail, Empty is a - // zero-sized repr(C) struct - // - the HList is layout-equivalent to an array of the same length as HList::LEN - let graph_slice = unsafe { - core::slice::from_raw_parts_mut(core::ptr::from_mut(&mut graph).cast(), G::LEN) - }; - let graph_len = expand_type_layout_graph_erased::(graph_slice, 0); - - assert!( - graph_len == G::LEN, - "bug: initialized graph has the wrong size" - ); - - // Safety: we have just checked that all array elements have been initialized - unsafe { graph.assume_init() } - } - - const fn fill_type_layout_graph_erased_reference< - A: TypeLayout, - G: 'static + Copy + Freeze + private::HList, - >() -> &'static G { - &const { fill_type_layout_graph_erased::() } - } - - // SAFETY: - // - HList is a sealed trait and is constructed here to be made of only Cons of - // TypeLayoutInfo and Empty - // - Cons is a repr(C) struct with a head followed by a tail, Empty is a - // zero-sized repr(C) struct - // - the HList is layout-equivalent to an array of the same length as HList::LEN - // - fill_type_layout_graph_erased_reference provides a static non-dangling - // reference that we can use to produce the data pointer for a slice - unsafe { - core::slice::from_raw_parts( - core::ptr::from_ref(const { fill_type_layout_graph_erased_reference::() }) - .cast(), - G::LEN, - ) - } - } + let layout = &T::TYPE_LAYOUT; - let info = &T::TYPE_LAYOUT; + // check if this type has already been inserted into the graph let mut it = &tys; while let Some(i) = it { - if str_eq(i.ty.name, info.name) { - if S::LEN == 0 { - return fill_type_layout_graph::(); + if type_layout_info_eq(i.ty, layout) { + // if no types remain, continue by computing the graph again, this + // time in a const with the now-known array hlist type + if RemainingTypes::LEN == 0 { + return compute_type_layout_graph_static_slice::(); } - return expand_type_layout_graph::(tys); + + // if more types remain, continue with recursion + return expand_type_layout_stack_graph_into_static_slice::< + GraphRoot, + GraphNodesArray, + RemainingTypes::Head, + RemainingTypes::Tail, + >(tys); } it = &i.next; } - if <::Concat as private::HList>::LEN == 0 { - return fill_type_layout_graph::, G>>(); + + if <::Concat as private::HList>::LEN + == 0 + { + // if no types remain, also considering the links from T, continue by + // computing the graph again, this time in a const with the now-known + // array hlist type + // the GraphNodesArray HList is extended by one element for T + return compute_type_layout_graph_static_slice::< + GraphRoot, + private::Cons<&'static TypeLayoutInfo<'static>, GraphNodesArray>, + >(); } - expand_type_layout_graph::< - A, - private::Cons<&'static TypeLayoutInfo<'static>, G>, - <::Concat as private::TypeHList>::Head, - <::Concat as private::TypeHList>::Tail, - >(Some(&Node { - ty: info, + + // if more types remain, continue with recursion, adding the links from T + // to the stack of remaining types + // the GraphNodesArray HList is extended by one element for T + expand_type_layout_stack_graph_into_static_slice::< + GraphRoot, + private::Cons<&'static TypeLayoutInfo<'static>, GraphNodesArray>, + <::Concat as private::TypeHList>::Head, + <::Concat as private::TypeHList>::Tail, + >(Some(&GraphStackNode { + ty: layout, next: tys, })) } -struct Node<'a> { +// on-stack linked list node that stores one type layout +struct GraphStackNode<'a> { ty: &'static TypeLayoutInfo<'static>, next: Option<&'a Self>, } +// transform the static reference to the hlist that's layout-equivalent to the +// array storing all type layouts into a static slice to the same array +const fn compute_type_layout_graph_static_slice< + GraphRoot: TypeLayout, + GraphNodesArray: 'static + Copy + Freeze + private::HList, +>() -> &'static [&'static TypeLayoutInfo<'static>] { + // SAFETY: + // - HList is a sealed trait and is constructed here to be made of only Cons of + // TypeLayoutInfo and Empty + // - Cons is a repr(C) struct with a head followed by a tail, Empty is a + // zero-sized repr(C) struct + // - the HList is layout-equivalent to an array of the same length as HList::LEN + // - fill_type_layout_graph_erased_reference provides a static non-dangling + // reference that we can use to produce the data pointer for a slice + unsafe { + core::slice::from_raw_parts( + core::ptr::from_ref(compute_type_layout_graph_static_array_ref::< + GraphRoot, + GraphNodesArray, + >()) + .cast(), + GraphNodesArray::LEN, + ) + } +} + +// create a static reference to the type layout hlist using an inline const +const fn compute_type_layout_graph_static_array_ref< + GraphRoot: TypeLayout, + GraphNodesArray: 'static + Copy + Freeze + private::HList, +>() -> &'static GraphNodesArray { + &const { compute_type_layout_graph_array::() } +} + +// create the hlist that's layout-equivalent to the array storing all type +// layouts and fill it with these type layouts +const fn compute_type_layout_graph_array( +) -> GraphNodesArray { + // layout-compatible with MaybeUninit::<[_; LEN]>::uninit() + let mut graph = MaybeUninit::::uninit(); + + // SAFETY: + // - HList is a sealed trait and is constructed here to be made of only Cons of + // TypeLayoutInfo and Empty + // - Cons is a repr(C) struct with a head followed by a tail, Empty is a + // zero-sized repr(C) struct + // - the HList is layout-equivalent to an array of the same length as HList::LEN + // - the mutable slice is to a slice of uninit elements, and an uninit array can + // always be accessed as an array of uninit elements + let graph_slice = unsafe { + core::slice::from_raw_parts_mut( + core::ptr::from_mut(&mut graph).cast(), + GraphNodesArray::LEN, + ) + }; + let graph_len = fill_type_layout_graph_slice::(graph_slice, 0); + + assert!( + graph_len == GraphNodesArray::LEN, + "bug: initialized graph has the wrong size" + ); + + // Safety: we have just checked that all array elements have been initialized + unsafe { graph.assume_init() } +} + +// compute the type graph by filling a slice of uninitialized type layouts and +// using it to check which types have already been seen +// once the graph is computed, return the number of elements initialized +const fn fill_type_layout_graph_slice( + tys: &mut [MaybeUninit<&'static TypeLayoutInfo<'static>>], + init_tys_len: usize, +) -> usize { + let layout = &T::TYPE_LAYOUT; + + // check if this type has already been inserted into the graph + let mut i = 0; + while i < init_tys_len { + // Safety: tys has been initialized for 0..tys_len + if type_layout_info_eq(unsafe { tys[i].assume_init_ref() }, layout) { + // if no types remain, return the initialized length of the array + if Remaining::LEN == 0 { + return init_tys_len; + } + + // if more types remain, continue with recursion + return fill_type_layout_graph_slice::( + tys, + init_tys_len, + ); + } + i += 1; + } + + // push the type layout into the slice to initialize the next element + assert!(init_tys_len < tys.len(), "bug: type layout graph too small"); + tys[init_tys_len] = MaybeUninit::new(layout); + + if <::Concat as private::HList>::LEN == 0 { + // if no types remain, also considering the links from T, return the + // initialized length of the array + return init_tys_len + 1; + } + + // if more types remain, continue with recursion, adding the links from T + // to the stack of remaining types + fill_type_layout_graph_slice::< + <::Concat as private::TypeHList>::Head, + <::Concat as private::TypeHList>::Tail, + >(tys, init_tys_len + 1) +} + +// simple type layout info equality by checking the equality of their type names +const fn type_layout_info_eq(a: &TypeLayoutInfo, b: &TypeLayoutInfo) -> bool { + str_eq(a.name, b.name) +} + const fn str_eq(a: &str, b: &str) -> bool { if a.len() != b.len() { return false;