I am no expert in const generics but I've tried a couple of different approaches, all with issues, when trying out new type instantiations that involve operating on const generics, for example: when trying to increment base in this const generic struct from K
to K+1
.
// Given a Base<K> return a Base<K+1>
pub struct Base<const K:u32> {}
pub const fn base_bump<const K: u32, const L: u32>(b: Base<K>,) -> Base<L> {
const L : u32 = K + 1;
Base::<L> {}
}
Error :
error[E0401]: can't use generic parameters from outer function
--> src/main.rs:5:20
|
2 | pub const fn base_bump<const K: u32, const L: u32>(
| - const parameter from outer function
...
5 | const l: u32 = K + 1;
| ^ use of generic parameter from outer function
For more information about this error, try `rustc --explain E0401`.
error: could not compile `playground` due to previous error
my understanding is that the current state of const generics refuses to instantiate new const generic
's from other const generics
s because const generic
s are types before being values. IOW, K
in
fn foo<const K: u32> () {}
is a type rather than a usual const value defined by const K : u32 = 1;
Although I will strongly mention here that the error messages aren't pointing the rational behind it.
Another issue arises when we try to do it like this:
pub struct Base<const K:u32> {}
// Given a Base<K> return a Base<K+1>
impl<const K : u32, const L: u32> Base<K> {
pub fn base_bump(&self) -> Base<L> {
todo!()
}
}
Error:
error[E0207]: the const parameter `L` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:3:27
|
3 | impl<const K : u32, const L: u32> Base<K> {
| ^ unconstrained const parameter
|
= note: expressions using a const parameter must map each value to a distinct output value
= note: proving the result of expressions other than the parameter are unique is not supported
Is there any way to achieve what I am trying to do here or should I abandon const generics and use a regular field to define the base here?
This is not true, but there are multiple issues with your code.
First, as the compiler is pointing out, the
const L
inside the function cannot refer to the function's generic parameterK
. This is becauseconst
s are compiled separately, even if inside a function (the only difference is being inaccessible to code outside the function, i.e. scoping).You should embed the computation:
But this still have multiple problems. First, you're declaring you're returning
Base
withL
chosen by the caller, but you are actually returning a constantK + 1
and notL
. You need to declare the function like:But this errors with:
Because this thing requires
#![feature(generic_const_exprs)]
. With it it works, but raises a warning:See this answer of mine for why this feature is especially hard.