Description
What is this
This is a design document for const generics. Any discussions about its content should be on zulip. The conclusions of these discussions should then be edited back into this issue. Please do not post any comments directly in this issue.
Content
We want to support the types of const parameters
to depend on other generic parameters.
fn foo<const LEN: usize, const ARR: [u8; LEN]>() -> [u8; LEN] {
ARR
}
This is currently forbidden during name resolution.
Generic const param types in type dependent paths
Probably the biggest blocker is type-checking const arguments
for generic parameters. This currently uses a hack
to supply the DefId
of the corresponding const parameter.
Now, let's look at the following:
fn foo<const N: usize, const M: [u8; N]>() {}
fn bar() {
foo::<3, { [0; 3] }>();
}
Here the expected type of { [0; 3] }
should be [u8; 3]
. With the
current approach it is [u8; N]
instead. To fix this we would have to
supply the affected queries the expected type of the const argument itself
or use a (DefId, SubstsRef<'tcx>)
pair instead.
Doing so isn't trivial because we have to worry about accidentially
ending up with different types for the same const argument which would
break stuff.
Potential dangers include partially resolved types and projections.
Variance for generic parameters used in const param types
The variance of a generic parameter used in the type of a const parameter should probably be influenced as if it was used in the type of a field.
// `T` is covariant because it is used in `DEFAULT`.
struct DefaultProvider<T, const DEFAULT: T>;
// `T` is invariant because it is used in `DEFAULT`.
struct WithItem<T: Iterator, const MAP: <T as Iterator>::Item>;