How can I safely initialise a constant of type `NonZeroU8`?

Viewed 185

The constructor of NonZeroU8 is a const fn, but it returns an Option, and Option.unwrap() is not a const fn, so the following won't compile:

use std::num::NonZeroU8;

const _: NonZeroU8 = NonZeroU8::new(7).unwrap();

The best work-around I've found is:

use std::num::NonZeroU8;

const _: NonZeroU8 = unsafe {NonZeroU8::new_unchecked(7)};

The use of "unsafe" is unsatisfying. Is there a safe way?

1 Answers

Panicking in const fns is currently unstable, which is why you can't use unwrap. A somewhat ugly, but stable workaround without using unsafe is to use something that implicitly panics, like out-of-bounds array indexing:

use std::num::NonZeroU8;

const VALUE: NonZeroU8 = match NonZeroU8::new(5) {
    Some(v) => v,
    None => [][0],
};

fn main() {
    println!("Value: {}", VALUE);
}

You can test this and note that changing the 5 to a 0 will cause a compile-time error. It's worth noting that within constants, new_unchecked will still cause compile-time errors for zero values, so it's fine to use that despite the unsafe.

Related