# Another approach to the nonzero macro

**URL:** <https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549>\
**Category:** language design\
**Created:** [August 23, 2026, 1:40pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549 "2026-08-23T13:40:24Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![TGODiamond](https://avatars.discourse-cdn.com/v4/letter/t/e9c0ed/32.png) [@TGODiamond](https://internals.rust-lang.org/u/TGODiamond)\
**Post date:** [August 23, 2026, 1:40pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/1 "2026-08-23T13:40:24Z")

</div>

Initialization of a nonzero number, where assertion happens at compile time:

```rust
// Using macro_rules for performant compilation, tested to work in stable Rust
#[macro_export]
macro_rules! nonzero {
    ($n:expr) => {
        // This is in a const context
        const {
            // Constant assertion that works even when running `cargo check`
            const _: () = {
                if $n == 0 { ::core::panic!("Cannot be zero!") }
            };

            // SAFETY: Checked that $n is not zero
            unsafe { ::core::num::NonZero::new_unchecked($n) }
        }
    };
}

```

This macro accepts all numbers that can be wrapped inside a nonzero, and returns it wrapped in a nonzero struct, as long as that number is not zero. Else, an evaluation panic will happen at compile time.

This API allows following patterns:

```rust
const MY_NUM: i32 = 1234; // Some constant defined in an external crate
    
const MY_NUM_AS_NONZERO: core::num::NonZero<i32> = nonzero!(MY_NUM);

```

```rust
// This code panics at compile time
let zero = nonzero!(1u16 - 1);

// But this compiles
let non_zero = nonzero!(1u16 + 1);

```

Is this something that could be implemented into the standard library?

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [August 23, 2026, 2:06pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/2 "2026-08-23T14:06:10Z")

</div>

Note that you can already write the following:

```rust
const MY_NUM_AS_NONZERO: NonZero<i32> = match NonZero::new(MY_NUM) {
    Some(nz) => nz,
    None => panic!("Cannot be zero!"),
};

```

Since this is totally safe there's less of a reason to do this in the stdlib.

On the other hand I think it might be more interesting to have dedicated literals for `NonZero`, or if we ever get some kind of custom literal or literal macros we could use those.

---

<div class="post-metadata">

**Author:** ![TGODiamond](https://avatars.discourse-cdn.com/v4/letter/t/e9c0ed/32.png) [@TGODiamond](https://internals.rust-lang.org/u/TGODiamond)\
**Post date:** [August 23, 2026, 3:24pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/3 "2026-08-23T15:24:17Z")

</div>

This is mostly an answer to how you can create a Vec using the `vec!` macro, but for NonZero numbers instead: By being short and concise. Though the `vec!` may only exist because it is not possible to do `Vec::from([1, 2, 3, 4])` in a constant context.

It is mostly a way to act like a literal without being one: It is much easier to implement this macro to the standard library than to make an enhanced literal system.

And this macro depends on stable `NonZero` anyway, so if said literal system where to be stabilized, it will conflict with it the same way as the `NonZero` struct does.

Also this macro will never panic in a run-time context.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [August 23, 2026, 3:56pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/4 "2026-08-23T15:56:48Z")

</div>

`Option::unwrap` and `expect` both work in `const` too.

---

<div class="post-metadata">

**Author:** ![chrefr](https://avatars.discourse-cdn.com/v4/letter/c/e480ec/32.png) [@chrefr](https://internals.rust-lang.org/u/chrefr)\
**Post date:** [August 23, 2026, 5:06pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/5 "2026-08-23T17:06:05Z")

</div>

You can do `const { NonZero::new(123).unwrap() }`, and while making it a macro will make that nicer, it'll need a strong justification to be in std.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [August 23, 2026, 5:47pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/6 "2026-08-23T17:47:50Z")

</div>

> [@TGODiamond](#):
>
> Is this something that could be implemented into the standard library?

I don't think so. Instead, `takes_nonzero(2)` should just work, same as how literals are already type-overloaded so that `takes_u8(2)` and `takes_i128(2)` both work.

---

<div class="post-metadata">

**Author:** ![tczajka](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tczajka/32/8923_2.png) [@tczajka](https://internals.rust-lang.org/u/tczajka)\
**Post date:** [August 23, 2026, 6:18pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/7 "2026-08-23T18:18:23Z")

</div>

Optimally you'd just write this:

```rust
const X: NonZero<i32> = 1234;

```

and similarly:

```rust
const X: BigInteger = 123123123123123123123123123123123123123123131;

```

This could work if there was a trait for integer literals and we had const traits.

---

<div class="post-metadata">

**Author:** ![TGODiamond](https://avatars.discourse-cdn.com/v4/letter/t/e9c0ed/32.png) [@TGODiamond](https://internals.rust-lang.org/u/TGODiamond)\
**Post date:** [August 23, 2026, 6:32pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/8 "2026-08-23T18:32:30Z")

</div>

I agree with both scott and tczajka. This is much better than using a macro.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [August 24, 2026, 7:24am UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/9 "2026-08-24T07:24:05Z")

</div>

Why does your macro nest const blocks inside each other? I don't see how that helps. I think your macro is just unnecessarily complicated.

> [@TGODiamond](#):
>
> Also this macro will never panic in a run-time context.

The same is true for `const { NonZero::new(123).unwrap() }`. So you could replace your entire macro by

```rust
macro_rules! nonzero {
    ($n:expr) => {
        const {
            ::core::num::NonZero::new($n).unwrap()
        }
    };
}

```

That is so simple that it doesn't really need a macro.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jrose/32/9591_2.png) [@jrose](https://internals.rust-lang.org/u/jrose)\
**Post date:** [August 24, 2026, 5:04pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/10 "2026-08-24T17:04:14Z")

</div>

I wouldn't quite say it doesn't need a macro. For literals, occupying space in a larger call or construction exception, it's a lot of verbiage over a plain integer, and I'd rather have a macro for it until the plain integer works. Whether or not that macro needs to live in the stdlib is an additional question though.

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [August 27, 2026, 12:55pm UTC](https://internals.rust-lang.org/t/another-approach-to-the-nonzero-macro/24549/11 "2026-08-27T12:55:47Z")

</div>

FWIW `.unwrap()/.expect()` do raise "syntactical alarm" bells which need to be soothed after the fact by spotting/pointing out the surrounding `const` context, which entails the error would be at compile-time, rather than at runtime (where tests could potentially miss the panic path).

Granted, to palliate that the macro can very much be defined by the user as part of some `utils` battery; but until we get _something_ in the language or stdlib, be it a macro, or some "magical from-literal through const traits" construction, these `NonZero<…>` types do feel rather second-class citizens, with higher usability hindrance than bare integers. I won't say which one would be the best solution here (between macros, some const-generic ctor\[1\], or whatnot), but only that we acknowledge that there is some (mild) problem at play, here

- Let's however note that an argument for a macro or built-in sugar for `NonZero` _literals_ (_i.e._, not allowing the OP's use case with `MY_NUM`) could have the advantage of, by virtue of being a syntactical check, being able to be a true compile-`check`-time assertion, so `cargo check/clippy` would catch these, rather than a post-mono error with all the limitations it has (notably, a post-mono-error based API does not seem suitable for the stdlib standard of quality, wherein `cargo check` and `cargo build` might disagree w.r.t. the success of compilation).

Though perhaps this overarching question would be more generally handled when dealing with pattern types, I don't know 🤔

* * *

1. 

```rust
impl NonZeroUsize {
   // "Compile-error" (codegen error) if `N == 0`.
   const fn new_const<const N: usize>() -> Self {
       const { Self::new(N).expect("expected the parameter to be non-zero") }
   }
}

// example:
let two = NonZeroUsize::new_const::<2>();

```
