Reputation: 434
Given sample struct:
struct S<const N: usize> {
arr: [u32; N] // I want size to be N > 0
}
I want to have N > 0.
In other words, I want to limit available values of N to be from range 1...MAX_USIZE
, and not 0...MAX_USIZE
.
Upvotes: 7
Views: 3516
Reputation: 73
If you want to use a where
clause you can do it like this:
#![feature(generic_const_exprs)]
pub enum Assert<const CHECK: bool> {}
pub trait IsTrue {}
impl IsTrue for Assert<true> {}
struct S<const N: usize> {
arr: [u32; N]
}
impl<const N: usize> S<N>
where
Assert<{N > 0}>: IsTrue
{
const fn new(arr: [u32; N]) -> Self {
S { arr }
}
}
Note:
generic_const_exprs
) and you need to use the nightly compiler for thismismatched types⏎expected constant false⏎ found constant true
)More about const generics in rust can be found on practice.rs (The Assert example can be found at the bottom of the page)
Upvotes: 5
Reputation: 71410
I would recommend assert!()
ing in the constructor, like @sebpuetz said, however it is possible to do that. This is bad (see this answer of mine for an explanation why, and why this is a hard problem in general), but you can use associated items for that:
struct S<const N: usize> {
arr: [u32; N],
}
impl<const N: usize> S<N> {
fn new(arr: [u32; N]) -> Self {
_ = <Self as AssertGt0>::VALID;
Self { arr }
}
}
trait AssertGt0 {
const VALID: ();
}
impl<const N: usize> AssertGt0 for S<N> {
const VALID: () = assert!(N > 0);
}
fn main() {
// _ = S::new([]); // This fails compilation
}
You cannot do that on where
clauses as far as I know, you have to use a constructor.
Upvotes: 5
Reputation: 2618
To my knowledge it's not possible to add such constraints to const generics as of now, a workaround is a constructor that asserts N > 0
:
struct S<const N: usize> {
arr: [u32; N] // I want size to be N > 0
}
impl<const N: usize> S<N> {
const fn new(arr: [u32; N]) -> Self {
assert!(N > 0, "n must be greater than 0");
S {
arr
}
}
}
const FAILS_TO_COMPILE: S<0> = S::new([]);
results in:
error[E0080]: evaluation of constant value failed
--> src/lib.rs:7:9
|
7 | assert!(N > 0, "n must be greater than 0");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the evaluated program panicked at 'n must be greater than 0', src/lib.rs:7:9
| inside `S::<0_usize>::new` at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panic.rs:57:9
...
14 | const FAILS_TO_COMPILE: S<0> = S::new([]);
| ---------- inside `FAILS_TO_COMPILE` at src/lib.rs:14:32
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
In non-const contexts, this is a runtime error.
Upvotes: 4