zst/lib.rs
1#![doc = include_str!("../README.md")]
2#![no_std]
3#![cfg_attr(
4 const_impl,
5 feature(const_trait_impl),
6 feature(const_default_impls),
7 feature(const_fn_trait_bound)
8)]
9
10#[cfg(feature = "const_default_impls")]
11use const_fn::const_fn;
12#[cfg(not(const_impl))]
13use unconst_trait_impl::unconst_trait_impl;
14use core::{default::Default, marker::PhantomData};
15#[cfg(const_impl)]
16use remove_macro_call::remove_macro_call;
17pub use the_assoc_ty_ext::TheAssocTyExt;
18
19/// [1-ZST](https://github.com/rust-lang/unsafe-code-guidelines/issues/172), i.e. one-aligned
20/// zero-sized type.
21///
22/// # Example
23/// ```rust
24/// use zst::ZST;
25/// use core::mem::{size_of, size_of_val};
26///
27/// // Repr is necessary to ensure the size of the discriminant
28/// #[repr(u8)]
29/// enum PrimUnsignedIntKinds {
30/// U8(ZST<u8>),
31/// U16(ZST<u16>),
32/// U32(ZST<u32>),
33/// U64(ZST<u64>),
34/// U128(ZST<u128>),
35/// Usize(ZST<usize>),
36/// }
37///
38/// assert_eq!(size_of::<ZST<u16>>(), 0);
39/// assert_eq!(
40/// size_of_val(&PrimUnsignedIntKinds::U16(ZST::<u16>::default())),
41/// size_of::<u8>()
42/// );
43/// // Since the ZST<T> is 1-aligned (#[repr(align(1))]), the following is guaranteed to hold
44/// assert_eq!(
45/// size_of::<PrimUnsignedIntKinds>(),
46/// size_of::<core::mem::Discriminant<PrimUnsignedIntKinds>>()
47/// );
48/// ```
49///
50// Since ZST is both Eq and and PartialEq, it has structural match
51// https://github.com/rust-lang/rust/issues/63438
52#[derive(Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, Copy)]
53#[repr(align(1))]
54pub struct ZST<T: ?Sized>(PhantomData<*const T>);
55
56#[cfg_attr(const_impl, remove_macro_call)]
57unconst_trait_impl! {
58 impl<T: ?Sized> const Default for ZST<T> {
59 fn default() -> Self {
60 ZST(Default::default())
61 }
62 }
63}
64
65#[cfg_attr(const_impl, remove_macro_call)]
66unconst_trait_impl! {
67 impl<T: ?Sized> const TheAssocTyExt for ZST<T> {
68 type TheAssocTy = T;
69 }
70}
71
72impl<T: ?Sized> ZST<T> {
73 #[cfg_attr(feature = "const_default_impls", const_fn)]
74 #[inline(always)]
75 pub fn new() -> ZST<T> {
76 Default::default()
77 }
78}