Encode size and alignment in the type system
joshlf opened this issue · 1 comments
Any design for this issue will interact with other issues tracked by #885; make sure to read that issue when tackling this one.
Without generic_const_exprs, we can't use size_of::<T>()
or align_of::<T>()
in a generic context. We have many use cases for these, so it would be good to work around the issue with a sort of polyfill.
In general, we'd like to be able to express in the type system:
size_of::<T>() == size_of::<U>()
align_of::<T>() >= align_of::<U>()
(useful for reference transmutations fromT
toU
)size_of::<T>() == N
align_of::<T>() >= N
or<= N
(to support #280)
API
The most obvious approach is to add machinery to KnownLayout
, although we need this machinery to not rely on const generics (like the associated LAYOUT
type currently does), so it would need to be a true type-level representation. It might be the case that:
- There are types we want to support which
KnownLayout
can't - There are types which
KnownLayout
currently supports which can't support this approach
Thus, we may need to introduce a separate trait or traits.
Given that the knowledge is now encoded in the type system, we need some way of expressing bounds. In other words, we need some sort of:
T: SizeEq<U>
T: AlignGtEq<U>
T: SizeEqConst<N>
T: AlignGtEqConst<N>
These could either be blanket impls in terms of KnownLayout
, or be separate from KnownLayout
entirely (and might need to be derived).
Merging #125 into this:
This is a half-baked idea, and it requires the unstable associated_const_equality feature. Also, the
AlignedTo
impls don't currently work thanks to rust-lang/rust#103292.trait Size { const SIZE: usize; } impl<T> Size for T { const SIZE: usize = core::mem::size_of::<T>(); } trait Align { const ALIGN: usize; } impl<T> Align for T { const ALIGN: usize = core::mem::align_of::<T>(); } trait Zst {} impl<T: Size<SIZE = 0>> Zst for T {} trait SameSizeAs<T> {} impl<const SIZE: usize, T: Size<SIZE = { SIZE }>, U: Size<SIZE = { SIZE }>> SameSizeAs<U> for T {} trait AlignedTo<T> {} impl<T: Align<ALIGN = 1>, U: Align<ALIGN = 1>> AlignedTo<U> for T {} impl<T: Align<ALIGN = 2>, U: Align<ALIGN = 2>> AlignedTo<U> for T {} impl<T: Align<ALIGN = 2>, U: Align<ALIGN = 1>> AlignedTo<U> for T {} impl<T: Align<ALIGN = 4>, U: Align<ALIGN = 4>> AlignedTo<U> for T {} impl<T: Align<ALIGN = 4>, U: Align<ALIGN = 2>> AlignedTo<U> for T {} impl<T: Align<ALIGN = 4>, U: Align<ALIGN = 1>> AlignedTo<U> for T {}