pub trait ConstDefault {
const DEFAULT: Self;
}
macro_rules! impl_cdef {
(<$A:ident> $def:expr => $($t:ty),+) => { $( $crate::impl_cdef![@<$A> $def => $t]; )+ };
(@<$A:ident> $def:expr => $t:ty) => {
impl<$A> $crate::ConstDefault for $t {
#[allow(clippy::declare_interior_mutable_const)]
const DEFAULT: Self = $def;
}
};
(<$A:ident:$A_:ident> $def:expr => $($t:ty),+) => {
$( $crate::impl_cdef![@<$A:$A_> $def => $t]; )+
};
(@<$A:ident:$A_:ident> $def:expr => $t:ty) => {
impl<$A: $crate::ConstDefault> $crate::ConstDefault for $t {
#[allow(clippy::declare_interior_mutable_const, reason = "FIXME?")]
const DEFAULT: Self = $def;
}
};
(<$A:ident, $B:ident> $def:expr => $($t:ty),+) => {
$( $crate::impl_cdef![@<$A, $B> $def => $t]; )+
};
(@<$A:ident, $B:ident> $def:expr => $t:ty) => {
impl<$A, $B> $crate::ConstDefault for $t {
#[allow(clippy::declare_interior_mutable_const)] const DEFAULT: Self = $def;
}
};
(<$A:ident:$A_:ident, $B:ident:$B_:ident> $def:expr => $($t:ty),+) => {
$( $crate::impl_cdef![@<$A:$A_, $B:$B_> $def => $t]; )+ };
(@<$A:ident:$A_:ident, $B:ident:$B_:ident> $def:expr => $t:ty) => {
impl<$A:$A_, $B:$B_> $crate::ConstDefault for $t {
#[allow(clippy::declare_interior_mutable_const)] const DEFAULT: Self = $def;
}
};
(<$A:ident, $B:ident, $C:ident> $def:expr => $($t:ty),+) => {
$( $crate::impl_cdef![@<$A, $B, $C> $def => $t]; )+
};
(@<$A:ident, $B:ident, $C:ident> $def:expr => $t:ty) => {
impl<$A, $B, $C> $crate::ConstDefault for $t {
#[allow(clippy::declare_interior_mutable_const)] const DEFAULT: Self = $def;
}
};
($def:expr => $($t:ty),+) => { $( $crate::impl_cdef![@$def => $t]; )+ };
(@$def:expr => $t:ty) => {
impl $crate::ConstDefault for $t {
#[allow(clippy::declare_interior_mutable_const)]
const DEFAULT: Self = $def;
}
};
(arrays <$A:ident:$BOUND:ident> $($LEN:literal),+) => {
$( $crate::impl_cdef![@array:$LEN <$A:$BOUND>]; )+
};
(@array:$LEN:literal <$A:ident:$BOUND:ident>) => {
impl<$A: $crate::ConstDefault> $crate::ConstDefault for [$A; $LEN] {
#[allow(clippy::declare_interior_mutable_const)] const DEFAULT: Self = [$A::DEFAULT; $LEN];
}
};
(tuples <$A:ident:$BOUND:ident>) => {
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,) => ($A::DEFAULT,)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,) => ($A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT,
$A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT,
$A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT,
$A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A,$A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT,
$A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A,$A,$A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT,
$A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
$crate::impl_cdef![@tuple <$A:$BOUND> ($A,$A,$A,$A,$A,$A,$A,$A,$A,$A,$A,$A) => ($A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT,
$A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT, $A::DEFAULT)];
};
(@tuple <$A:ident:$BOUND:ident> $type:ty => $value:expr) => {
impl<$A: $crate::ConstDefault> $crate::ConstDefault for $type {
const DEFAULT: Self = $value;
}
};
}
pub(crate) use impl_cdef;
#[rustfmt::skip]
mod impl_core {
use super::{impl_cdef, ConstDefault};
use core::{
cmp::Reverse,
cell::{Cell, OnceCell, RefCell, UnsafeCell},
ffi::CStr,
marker::{PhantomData, PhantomPinned},
mem::ManuallyDrop,
num::{Saturating, Wrapping},
ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
panic::AssertUnwindSafe,
time::Duration,
};
impl_cdef![false => bool];
impl_cdef![Duration::new(0, 0) => Duration];
impl_cdef![0 => i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize];
impl_cdef![0.0 => f32, f64];
impl_cdef!['\x00' => char];
impl_cdef![() => ()];
impl_cdef![tuples <T: ConstDefault>];
impl_cdef![arrays <T: ConstDefault> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32];
impl_cdef![<T> core::ptr::null() => *const T];
impl_cdef![<T> core::ptr::null_mut() => *mut T];
impl_cdef![<T> &[] => &[T]]; impl ConstDefault for &CStr {
const DEFAULT: Self = {
if let Ok(s) = CStr::from_bytes_until_nul(&[0]) { s } else { unreachable![]; }
};
}
impl_cdef![Self => PhantomPinned, RangeFull];
impl_cdef![<T: ConstDefault>Self { start: T::DEFAULT } => RangeFrom<T>];
impl_cdef![<T: ConstDefault>Self { end: T::DEFAULT } => RangeTo<T>, RangeToInclusive<T>];
impl_cdef![<T: ConstDefault>Self { start: T::DEFAULT, end: T::DEFAULT } => Range<T>];
impl_cdef![<T: ConstDefault>Self::new(T::DEFAULT, T::DEFAULT) => RangeInclusive<T>];
impl_cdef![<T: ConstDefault> Self::new() => OnceCell<T>];
impl_cdef![<T: ConstDefault> Self::new(T::DEFAULT) =>
Cell<T>, ManuallyDrop<T>, RefCell<T>, UnsafeCell<T>
];
impl_cdef![<T: ConstDefault> Self(T::DEFAULT) =>
AssertUnwindSafe<T>, Reverse<T>, Saturating<T>, Wrapping<T>
];
impl_cdef![<T> Self => PhantomData<T>]; impl_cdef![<T: ConstDefault> Some(T::DEFAULT) => Option<T>];
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "std")))]
mod impl_std {
use std::{
cell::LazyCell,
process::ExitCode,
sync::{Condvar, LazyLock, Mutex, Once, OnceLock, RwLock, Weak as ArcWeak},
};
impl_cdef![Self::SUCCESS => ExitCode];
impl_cdef![Self::new() => Condvar, Once];
impl_cdef![<T: ConstDefault> Self::new() => ArcWeak<T>, OnceLock<T>];
impl_cdef![<T: ConstDefault> Self::new(T::DEFAULT) => Mutex<T>, RwLock<T>];
impl_cdef![<T: ConstDefault> Self::new(|| T::DEFAULT) => LazyCell<T>, LazyLock<T>];
}