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:
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:
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
|