3 releases
0.1.2 | Jul 17, 2022 |
---|---|
0.1.1 | Feb 18, 2022 |
0.1.0 | Feb 14, 2022 |
#2015 in Rust patterns
Used in nalgebra_latex
9KB
52 lines
Zero-sized generic type with the associated type exposing the type parameter
One good way to represent types themselves as opposed to the values thereof is to use zero-sized types, which are commonly abbreviated as ZSTs. A programmer can have an enum whose variants store the corresponding ZST (and, implicitly, the enum discriminant that may or may not be optimized out); and then the size of the enum will not depend on the size of the types that are being represented.
At the time of writing, there is no canonical wrapper that would allow one to get ZST representing a type. The closest alternative is core::marker::PhantomData
, yet the semantics of PhantomData
is unnecessarily richer and has undesirable tradeoffs between generality/ease-of-use, for this, secondary use case.
Note: Even more precisely, the desired ZST<T>
generic ZST New Type is close to PhantomData<*const T>
.
Since ZST<T>
must represent T
, it is natural to desire accessing the associated type. It is possible with the TheAssocTy
associated type.
Example
use zst::ZST;
use core::mem::{size_of, size_of_val};
// Repr is necessary to ensure the size of the discriminant
#[repr(u8)]
enum PrimUnsignedIntKinds {
U8(ZST<u8>),
U16(ZST<u16>),
U32(ZST<u32>),
U64(ZST<u64>),
U128(ZST<u128>),
Usize(ZST<usize>),
}
assert_eq!(size_of::<ZST<u16>>(), 0);
assert_eq!(
size_of_val(&PrimUnsignedIntKinds::U16(ZST::<u16>::default())),
size_of::<u8>()
);
// Since the ZST<T> is 1-aligned (#[repr(align(1))]), the following is guaranteed to hold
assert_eq!(
size_of::<PrimUnsignedIntKinds>(),
size_of::<core::mem::Discriminant<PrimUnsignedIntKinds>>()
);
Note: core::mem::Discriminant
, as the doc states, is opaque. Similarly, the data layout of any enum
is rather vaguely specified for performance considerations. You can learn the deailts in Unsafe Code Guidelines Reference.
Dependencies
~1.5MB
~36K SLoC