This is a problem exclusively for when there is a const RUNTIME: bool param added to all const traits.
Let's say each trait now has a const RUNTIME: bool param if they support const contexts, and trait Foo<T> is one of the const traits. Where do we put the param?
Well, I think there are two obvious choices. Either RUNTIME is at the beginning, or it is at the end, next to all the generic parameters the user has written. Putting it in the middle.. has zero sense whatsoever.
Let's talk about why we'd want to choose both.
First of all, a lot of the implementation hassle is reduced by making this parameter default to true (so default to a non-const trait). This would allow someone to refer to T: Foo<()> with zero friction/special-casing in the compiler needed to modify the lowering to make that default to a trait that is non-const. This is not so great if the parameter is at the beginning, as that requires us to shift everything when we actually desugar with the new parameter inserted.
But, putting the RUNTIME parameter at the end creates trouble for us if default types refer to it! Consider the following:
#[const_trait]
trait Foo<N, T = <N as ~const Add>::Output> {}
This is a problem exclusively for when there is a
const RUNTIME: bool
param added to all const traits.Let's say each trait now has a
const RUNTIME: bool
param if they support const contexts, andtrait Foo<T>
is one of the const traits. Where do we put the param?Well, I think there are two obvious choices. Either
RUNTIME
is at the beginning, or it is at the end, next to all the generic parameters the user has written. Putting it in the middle.. has zero sense whatsoever.Let's talk about why we'd want to choose both.
First of all, a lot of the implementation hassle is reduced by making this parameter default to
true
(so default to a non-const trait). This would allow someone to refer toT: Foo<()>
with zero friction/special-casing in the compiler needed to modify the lowering to make that default to a trait that is non-const. This is not so great if the parameter is at the beginning, as that requires us to shift everything when we actually desugar with the new parameter inserted.But, putting the
RUNTIME
parameter at the end creates trouble for us if default types refer to it! Consider the following:If we put
RUNTIME
at the end, we'd be in trouble! SinceT
refers toRUNTIME
in its~const Add
bound, the compiler errors because it doesn't support this in type defaults! Before we switched to the new desugaring, @fmease made two attempts but AFAIK did not get very far with them: https://github.com/rust-lang/rust/pull/120028 and https://github.com/rust-lang/rust/pull/120029.This is a problem discovered by @fmease (feel free to elaborate this issue summary, or correct it if it is wrong). This comment begins discussing it.