my attempt to code a nonzero macro... will I go straight to macro jail?

89 points Sweet-Ad-597 47 comments

DISCLAIMER: It's more of a "recreational" project than something I'd use in production. Don't ask me, "Do you truly need it?" The answer is no.

So I was happily programming in rust and boom I needed to work with NonZero numbers and it felt wrong to waste time doing NonZero::new(3).unwrap() because I know for a fact that 3 is not 0, but to write it without an extra runtime cost I have to writeNonZero::new_unchecked(3), but that requires an unsafe block.

My aim with the macro was to create a compile-time-checked NonZero with as little runtime cost as possible... and I ended up with this:

#[macro_export]
macro_rules! nonzero {
    (0) => {
        compile_error!("Believe it or not, 0 is NOT a non-zero value.")
    };
    ($n:literal) => {
        // SAFETY: the number is guaranteed not to be 0 due to the first rule of the nonzero macro.
        const { unsafe { ::core::num::NonZero::new_unchecked($n) } }
    };
    ($n:expr) => {
        const {
            if $n == 0 {
                panic!("Believe it or not, 0 is NOT a non-zero value.")
            }

            // SAFETY: Checked for zeros above.
            unsafe { ::core::num::NonZero::new_unchecked($n) }
        }
    }
}