# How do I static assert a property of a generic u32 parameter?

**URL:** <https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307>\
**Category:** uncategorized\
**Created:** [May 30, 2022, 10:51pm UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307 "2022-05-30T22:51:23Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jgarvin](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/jgarvin/32/16213_2.png) [@jgarvin](https://users.rust-lang.org/u/jgarvin)\
**Post date:** [May 30, 2022, 10:51pm UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/1 "2022-05-30T22:51:23Z")

</div>

I tried a bunch of different ways based on reading snippets, and I haven't found any that compile. Interestingly rustc doesn't even suggest any feature flags for this which makes me wonder if what I'm trying to do is impossible even with nightly?

```rust
//fn test<const N: u32>()
//{
// const _ = assert!(N % 4 == 0);
//}

//fn test2<const N: u32>()
// where [(); N % 4 == 0]:
//{
//}

//const fn check(n: u32) -> bool
//{
// return n % 4 == 0;
//}

//fn test3<const N: u32>()
//{
// const _ = assert!(check(N));
//}

//const fn check2<N: u32>() -> bool
//{
// return N % 4 == 0;
//}

//fn test4<const N: u32>()
//{
// const _ = assert!(check::<N>());
//}

```

[Playground link](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2015&gist=46516a183c7b882498105a2df84f95be). In the past I did get this kind of check working once with `typenum`, but the compiler errors were worse than the ones I'd get in C++ so I don't think that's a practical route esp. if I have to support this code being used by others.

---

<div class="post-metadata">

**Author:** ![LegionMammal978](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/legionmammal978/32/25560_2.png) [@LegionMammal978](https://users.rust-lang.org/u/LegionMammal978)\
**Post date:** [May 30, 2022, 11:25pm UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/2 "2022-05-30T23:25:42Z")

</div>

One workaround (which I found [here](https://github.com/nvzqz/static-assertions-rs/issues/40#issuecomment-846228355)) is to evaluate an associated constant ([Rust Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2015&gist=6da9013951da140a7a67716d285bde26)):

```rust
struct AssertDivisible<const N: u32, const D: u32>;

impl<const N: u32, const D: u32> AssertDivisible<N, D> {
    const OK: () = assert!(N % D == 0, "must be divisible");
}

fn test<const N: u32>() {
    let () = AssertDivisible::<N, 4>::OK;
}

```

This can be adapted to pretty much any constant-evaluated condition. However, a new type must be used for every kind of condition, since no operations can be done on the const generic parameters themselves.

---

<div class="post-metadata">

**Author:** ![jgarvin](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/jgarvin/32/16213_2.png) [@jgarvin](https://users.rust-lang.org/u/jgarvin)\
**Post date:** [May 31, 2022, 2:18am UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/3 "2022-05-31T02:18:35Z")

</div>

> [@LegionMammal978](#):
>
> However, a new type must be used for every kind of condition, since no operations can be done on the const generic parameters themselves.

Not sure I understand. It looks like you are doing operations on generic parameters? I think you mean you need a new type each time because if you put multiple associated consts for different conditions in the same impl they would all get triggered at once when the impl is instantiated?

---

<div class="post-metadata">

**Author:** ![vague](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/vague/32/21401_2.png) [@vague](https://users.rust-lang.org/u/vague)\
**Post date:** [May 31, 2022, 2:31am UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/4 "2022-05-31T02:31:03Z")

</div>

```rust
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

fn test2<const N: u32>()
    where [(); (N % 4 == 0) as usize -1]: {
}

```

---

<div class="post-metadata">

**Author:** ![LegionMammal978](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/legionmammal978/32/25560_2.png) [@LegionMammal978](https://users.rust-lang.org/u/LegionMammal978)\
**Post date:** [May 31, 2022, 2:58am UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/5 "2022-05-31T02:58:40Z")

</div>

What I mean is that the actual arithmetic and comparisons must be done in the value of the associated constant. The type parameters to `Assert` must pass through the values directly. So we can't write, e.g., `struct Assert<const COND: bool>;` with `const OK: () = assert!(COND);` and test `Assert::<{ N % 4 == 0 }>::OK`, at least not without `generic_const_exprs`. As a collorary, if we want to test several different conditions, we need several different `Assert` types, each with a condition in its `OK` constant.

---

<div class="post-metadata">

**Author:** ![jgarvin](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/jgarvin/32/16213_2.png) [@jgarvin](https://users.rust-lang.org/u/jgarvin)\
**Post date:** [May 31, 2022, 3:53am UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/6 "2022-05-31T03:53:48Z")

</div>

Got it, thanks👍

---

<div class="post-metadata">

**Author:** ![Michael-F-Bryan](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/michael-f-bryan/32/28749_2.png) [@Michael-F-Bryan](https://users.rust-lang.org/u/Michael-F-Bryan)\
**Post date:** [May 31, 2022, 8:54am UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/7 "2022-05-31T08:54:47Z")

</div>

What about using `const_assert!()` from [the `static-assertions` crate](https://docs.rs/static_assertions/latest/static_assertions/macro.const_assert.html)?

```rust
const VALUE: i32 = // ...

static_assertions::const_assert!(VALUE >= 2);

```

---

<div class="post-metadata">

**Author:** ![Yandros](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/yandros/32/8136_2.png) [@Yandros](https://users.rust-lang.org/u/Yandros)\
**Post date:** [May 31, 2022, 11:06am UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/8 "2022-05-31T11:06:19Z")

</div>

> [@jgarvin](#):
>
> Interestingly rustc doesn't even suggest any feature flags for this which makes me wonder if what I'm trying to do is impossible even with nightly?

With `nightly` you have @vague's answer, which is the proper solution.

* * *

On stable, you can use **post-monomorphization errors** (`panic!`s when resolving generic constants) to emulate that, but it's really a poorman's substitute, since `cargo check` won't detect those failures, only the final `cargo build` can, and it will only do so if such a function is deemed reachable enough for it to make it to codegen (thence triggering a monomorphization of that generic const, and thus, observing the panic). This is what @LegionMammal978's solution is about, but it was missing these obligatory disclaimers about the limitations of post-mono errors

- In other words: if you're compiling the final binary, an approach based on post-mono checks is fine. But if you're just a library, then you may make mistakes which you'll never detect and only a downstream user will, which will be highly inconvenient for them. _So I would advise against post-mono checks for library authors._

* * *

On the other hand, @LegionMammal978's approach has the advantage of using a compile-time panic for a way nicer error message. So we can take that idea and apply it to the `nightly` approach, yielding:

```rust
struct AssertDivisibleBy4<const N: u32>;

impl<const N: u32> AssertDivisibleBy4<N> {
    const OK: usize = {
        assert!(N % 4 == 0, "must be divisible by 4");
        0
    };
}

fn test2<const N: u32> ()
where
    [(); AssertDivisibleBy4::<N>::OK]:,
{
    // …
}

```

so that a `test2::<3>`, even in unreachable code, yields:

```rust
error[E0080]: evaluation of `AssertDivisibleBy4::<3_u32>::OK` failed
 --> src/lib.rs:8:9
  |
8 | assert!(N % 4 == 0, "must be divisible by 4");
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'must be divisible by 4', src/lib.rs:8:9
  |

```

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [August 29, 2022, 11:06am UTC](https://users.rust-lang.org/t/how-do-i-static-assert-a-property-of-a-generic-u32-parameter/76307/9 "2022-08-29T11:06:44Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
