Description
Consider the following code:
trait Foo {
const VAL: usize;
}
trait MyTrait {}
trait True {}
struct Is<const T: bool>;
impl True for Is<{true}> {}
impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
Coherence checking needs to determine whether the two MyTrait
impls can ever overlap. This requires determining (among other things) if {T::VAL == 5}
and {T::VAL == 6}
will ever have the same value - if they do, then the impls will overlap.
In this case, we can see that T::VAL == 5
and T::VAL == 6
can never both be true. However, in the general case, we could have an expression like Is<{someConstFn(T::VAl)}
. Coherence checking would need to determine if two const functions will ever produce the same value for a given input. This seems impossible without radically extending the Rust language and/or the abilities of the compiler.
One solution would be to ban any const projections within where
clauses. That is, where Is<{2 + 2 == 5}>: True
would be allowed, but where Is<{T::VAL == T::VAL}>: True
would not be. This would ensure that it's always possible to fully const-eval an expression during coherence checking, which allows us to be certain about whether or not two impls overlap.