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?