Failure within a Macro

⚓ Rust    📅 2025-06-30    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 41 days ago. The information described in this article may have changed.

Info

This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Failure within a Macro

Hi, I have a crate called nonempty-collections, within which is the following macro:

macro_rules! nev {
    () => {compile_error!("An NEVec cannot be empty")};
    ($h:expr, $( $x:expr ),* $(,)?) => {{
        let mut v = $crate::NEVec::new($h);
        $( v.push($x); )*
        v
    }};
    ($h:expr) => {
        $crate::NEVec::new($h)
    }
}

This allows the syntax nev![1,2,3] for creating an NEVec. The macro behaves identically to vec!, save that it also accounts for the empty case and proactively warns the user at compile time, as you can see with the compile_error! line. LSPs likewise add a red squiggle if you type nev![].

Now, we're attempting to extend this to support nev!["foo"; 3] syntax, which vec! also allows. This repeats the given element N times, so in this case something like ["foo", "foo", "foo"].

However, I'm having a hell of time trying to use compile_error! for this. The internet advertises that the addition of the following case should work:

    ($elem:expr; $n:expr) => {{
        match std::num::NonZeroUsize::try_from($n) {
            Ok(z) => $crate::vector::from_elem($elem, z),
            Err(_) => compile_error!("n cannot be 0"),
        }
    }};

No matter what value I pass to the macro as N, it triggers the n cannot be 0 message. More manual hacks this like also don't work:

        const VAL: usize = $n;

        if VAL > 0 {
            $crate::vector::from_elem($elem,  unsafe { std::num::NonZeroUsize::new_unchecked(VAL) })
        } else {
            compile_error!("n cannot be 0")
        }

Have I fundamentally misunderstood how compile_error! works?

3 posts - 3 participants

Read full topic

🏷️ rust_feed