After talking to lcnr and eddyb, I have updated the proposal for the MVP. Feedback again requested.
Which types a const parameter can be
In the MVP, we will only allow the integral primitives to be const parameters: signed and unsigned integer types, booleans, and chars.
Extending to all types with structural equality would be a near-term extension after the MVP.
Which expressions can be applied as a const parameter
In the MVP, const parameters can only contain these two kinds of expressions:
- Const parameters as identity expressions - that is if
N
is a free const parameter, it can only be applied as a const parameter as the expressionN
. - Const expressions containing no free type or const parameters.
We will implement this behavior by refusing to resolve const and type parameters when computing a const parameter expression, except to implement the first case.
Which locations a const parameter can be used in
There will be no limitation on where const parameters can be used - they can be used on any item a type parameter could be used on, and in constraints, and so on.
We had a good discussion about this in zulip and determined that it isn't necessary. Basically, without lazy normalization there are two problems. First, users sometimes get bizarre cycle errors that are actually incorrect, and lazy normalization will resolve correctly. Second, the current implementation actually allows some code that should not be allowed, because it resolves an associated item that should be ambiguous. This means lazy normalization will break some hypothetical code. For example:
trait Trait<T> {
const ASSOC_CONST: usize = 0;
}
impl Trait<()> for u8 {}
// `u8::ASSOC_CONST` is resolved today, but will be ambiguous
// under lazy normalization
type Foo<T, U>
where u8: Trait<T> + Trait<U>
= [(T, U); u8::ASSOC_CONST];
This is not great. However, these examples are not easy to hit under the restrictions we've identified above, are basically pathological, and (importantly) are already allowed on stable because we allow consts in all these positions on stable by way of allowing arrays in all these positions.
So we will not limit where consts are allowed, but we will also not block const generics on lazy normalization.