# Safe const NonZero values

**URL:** <https://internals.rust-lang.org/t/safe-const-nonzero-values/21080>\
**Category:** Uncategorized\
**Created:** [June 25, 2024, 4:05pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080 "2024-06-25T16:05:58Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![NevinFlanagan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nevinflanagan/32/12285_2.png) [@NevinFlanagan](https://internals.rust-lang.org/u/NevinFlanagan)\
**Post date:** [June 25, 2024, 4:05pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/1 "2024-06-25T16:05:58Z")

</div>

I'm finding myself writing a LOT of `unsafe { NonZero::new_unchecked(1) }` and similar lines. It seems like language updates facilitate a more compact syntax such as `NonZero::new_const::<1>()`. This seems like it could be implemented along the lines of

```rust
impl NonZero<u8> {
    const fn new_const<const N: u8>() -> Self {
        const {assert!(N != 0, "can't initialize NonZero value as 0"); }
        Self(N)
    }
}

```

---

<div class="post-metadata">

**Author:** ![pitaj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pitaj/32/11262_2.png) [@pitaj](https://internals.rust-lang.org/u/pitaj)\
**Post date:** [June 25, 2024, 4:10pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/2 "2024-06-25T16:10:46Z")

</div>

I think this will be better solved by pattern types:

```rust
impl NonZeroU8 {
    pub fn from(n: u8 is 1..) {
        Self(n)
    }
}

```

In the meantime you may as well use `NonZero::new(1).unwrap()` because it will easily optimize away.

Edit: I see unwrap is still const-unstable, in const contexts `new_unchecked` will still be necessary.

---

<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:** [June 25, 2024, 4:27pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/3 "2024-06-25T16:27:16Z")

</div>

> [@pitaj](#):
>
> Edit: I see unwrap is still const-unstable, in const contexts `new_unchecked` will still be necessary.

You can use `match` and `panic!()`/`unreachable!()` in the `None` branch, which is possible on stable since 1.57

```rust
let one = const {
    match NonZeroU8::new(1) {
        Some(one) => one,
        None => unreachable!(),
    }
};

```

---

<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:** [June 25, 2024, 6:00pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/4 "2024-06-25T18:00:25Z")

</div>

> [@NevinFlanagan](#):
>
> I'm finding myself writing a LOT of

You can eliminate the repetitiveness by defining a function that does it.

The best way to handle this in the language would be to allow literals like `1` to have this type too. Even better if any custom types could have integer literals.

---

<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:** [June 25, 2024, 6:08pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/5 "2024-06-25T18:08:26Z")

</div>

> [@pitaj](#):
>
> by pattern types

Of course, once we have pattern types we won't really need `NonZeroU8` any more 🙃

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [June 25, 2024, 7:08pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/6 "2024-06-25T19:08:51Z")

</div>

Pattern types is something that may or may not exist, and if it ends up stabilized it may be 10 years from now.. this API is something that can be added right now

And also: NonZero may well become deprecated once pattern types is stabilized!

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [June 25, 2024, 8:13pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/7 "2024-06-25T20:13:46Z")

</div>

There are interesting rules around pattern-restricted types that can result in `u8 is 1..` and `NonZeroU8` behaving differently if we want the intuitive subtyping rules to work out. So I don't think `NonZero<_>` will end up fully deprecated, just used in APIs a lot less.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [June 25, 2024, 9:42pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/8 "2024-06-25T21:42:32Z")

</div>

What would be really awesome is if the compiler had support for using the literal syntax so there's no need to define any sort of special constructor method whose need might be obviated by future compiler features like const `unwrap()`:

```rust
const FOO: NonZero<u8> = 42;

```

Something like this would cause a compile error:

```rust
const FOO: NonZero<u8> = 0;

```

Not sure what blocked this sort of thing before with e.g. `NonZeroU8` but with `NonZero<T>` it seems there's now at least only one type that needs some magic compiler assistance.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [June 25, 2024, 10:40pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/9 "2024-06-25T22:40:51Z")

</div>

> [@bascule](#):
>
> Not sure what blocked this sort of thing before

The primary thing is that type inference/fallback around the `{integer}` placeholder inference type is extremely ad-hoc and hacky, and adding new types into the set is likely to cause inference breakage, that breakage has reasonable potential to be widespread, and there's no good way to keep it from immediately being stable (as trait impls generally always are).

(E.g. you can sometimes call methods directly on `{integer}`, if they come from a trait. If the method is shadowed by an inherent method, calling it twice can call either method depending on context, without any compiler warnings. It's a textbook example of spooky action at distance.)

There's interest in migrating it to a trait, but removing the pile of special cases quickly runs headfirst into the thorny problem that is [defaults that affect type inference](https://faultlore.com/blah/defaults-affect-inference/#defaults-affect-inference). The discussion on the old [tracking issue](https://github.com/rust-lang/rust/issues/27336) covers some of the [hairy questions](https://github.com/rust-lang/rust/issues/27336#issuecomment-229988042) that led to closing that issue.

AIUI this is one of the things that the new inference engine / trait solver should unblock, and everyone with the ability to do so is focused on moving that work forward in leu of extending the current system.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [June 25, 2024, 10:51pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/10 "2024-06-25T22:51:39Z")

</div>

I tried this a couple years ago. It's easier said than done, unfortunately.

---

<div class="post-metadata">

**Author:** ![binarycat](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/binarycat/32/12210_2.png) [@binarycat](https://internals.rust-lang.org/u/binarycat)\
**Post date:** [June 27, 2024, 12:51am UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/11 "2024-06-27T00:51:18Z")

</div>

> [@NevinFlanagan](#):
>
> It seems like language updates facilitate a more compact syntax

more important than compactness is saftey. `NonZeroU8::new_unchecked(0)` is immediate undefined behavior, even though most users wouldn't mind the additional cost of a check+panic.

> [@jhpratt](#):
>
> I tried this a couple years ago. It's easier said than done, unfortunately.

const functions have become a _ **lot** _ less limited than they were a few years ago.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [June 27, 2024, 3:35am UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/12 "2024-06-27T03:35:03Z")

</div>

> [@binarycat](#):
>
> const functions have become a _ **lot** _ less limited than they were a few years ago.

The limitations of `const` was hardly an issue then (and it hasn't improved here, as const traits are needed). It was a matter of being able to implement it on the language side of things.

---

<div class="post-metadata">

**Author:** ![binarycat](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/binarycat/32/12210_2.png) [@binarycat](https://internals.rust-lang.org/u/binarycat)\
**Post date:** [June 27, 2024, 4:49am UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/13 "2024-06-27T04:49:14Z")

</div>

why do you need const traits? why not just do a zero check then call new\_unchecked?

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [June 27, 2024, 1:01pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/14 "2024-06-27T13:01:22Z")

</div>

It was intended to be a general purpose mechanism to avoid adding roughly a dozen new lang items.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [September 25, 2024, 1:01pm UTC](https://internals.rust-lang.org/t/safe-const-nonzero-values/21080/15 "2024-09-25T13:01:33Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
