?play
use std::num::*;
#[doc(hidden)]
pub struct __NzDispatcherConstructor<T>(T);
#[doc(hidden)]
pub struct __NzDispatcher<const N: usize>(AnyInt);
#[doc(hidden)]
pub trait __NzType {
type Nz;
}
impl<T> __NzDispatcherConstructor<T> {
pub const fn __new(val: T) -> Self {
Self(val)
}
}
macro_rules! impl_nz {
([] [$($union_fields:tt)*] [$($counter:tt)*] ) => {
#[doc(hidden)]
pub union AnyInt { $($union_fields)*}
};
([$int:ident : $nz:ident, $($tail:tt)*] [$($union_fields:tt)*] [$($counter:tt)*] ) => {
#[allow(non_upper_case_globals)]
const $int: usize = {
let h: &[()] = &[$($counter)*];
h.len()
};
impl __NzDispatcherConstructor<$int> {
#[must_use]
pub const fn erase_with_id(self) -> (usize, AnyInt) {
($int, AnyInt {$int: self.0})
}
}
impl __NzDispatcher<{$int}> {
#[must_use]
pub const fn __new(expr: AnyInt) -> Self {
Self(expr)
}
#[must_use]
pub const fn __make_nz(self) -> $nz {
let inner = unsafe { self.0.$int };
match $nz::new(inner) {
Some(x) => x,
None => panic!("Attempt to construct a non-zero constant with a value of zero")
}
}
}
impl __NzType for __NzDispatcher<{$int}> {
type Nz = $nz;
}
impl_nz!{[$($tail)*] [$int: $int, $($union_fields)*] [(), $($counter)*]}
};
}
impl_nz! {
[i8: NonZeroI8,
u8: NonZeroU8,
i16: NonZeroI16,
u16: NonZeroU16,
i32: NonZeroI32,
u32: NonZeroU32,
i64: NonZeroI64,
u64: NonZeroU64,
i128: NonZeroI128,
u128: NonZeroU128,
isize: NonZeroIsize,
usize: NonZeroUsize,
]
[]
[]
}
#[macro_export]
macro_rules! nz {
($e:expr) => {
{
const __ERASED_ID_AND_EXPR: (usize, $crate::AnyInt) = $crate::__NzDispatcherConstructor::__new($e).erase_with_id();
const __ID: usize = __ERASED_ID_AND_EXPR.0;
const __ERASED: $crate::AnyInt = __ERASED_ID_AND_EXPR.1;
const __EXPR: <$crate::__NzDispatcher<__ID> as $crate::__NzType>::Nz = $crate::__NzDispatcher::<__ID>::__new(__ERASED).__make_nz();
__EXPR
}
};
}
fn main() {
let x = nz!(64u8);
const FOO: usize = 10;
let y = nz!(1 + FOO);
let z = nz!(123i32 + 40 + FOO as i32);
dbg!((x, y, z));
}