Const bool generic doesn't understand exhaustiveness implementation

trait MyTrait {
    fn conditional_method(&self) -> u64;
}

trait MyStructConditionalHelper<const COND: bool> {
    fn conditional_method(&self) -> u64;
}
struct MyStruct<const COND: bool>;

impl<const COND: bool> MyStructConditionalHelper<true> for MyStruct<COND> {
    fn conditional_method(&self) -> u64 {
        42
    }
}

impl<const COND: bool> MyStructConditionalHelper<false> for MyStruct<COND> {
    fn conditional_method(&self) -> u64 {
        0
    }
}

impl<const COND: bool> MyTrait for MyStruct<COND> {
    fn conditional_method(&self) -> u64 {
        <Self as MyStructConditionalHelper<COND>>::conditional_method(self)
    }
}

Seems like rustc doesn't understand that there are only two possible values for bool. By implementing both Trait<true> and Trait<false> on a struct I can not generically cast the struct, Struct<COND: bool>, to Trait<COND: bool>. This caught me by surprise. Does someone know if there is plan to support this?

hmm, I solved it myself :man_facepalming:

by adding

where
    Self: MyStructConditionalHelper<COND>

rustc is able to understand that the trait exists. Could someone explain this to me? :folded_hands:

Without that where bound, there's nothing stated to prove that the struct implements the trait. I feel like this restriction helps with local reasoning, too, in case the true/false trait impls are far away (in the same crate).

With that bound, it pushes the true/false exhaustive checking to the use sites that make use of the MyTrait, which seems like a much easier context to prove the one const value is covered.

Interesting questions for considering not needing this bound:
For a u8 const parameter, would the compiler to keep track of the full coverage?
What about u64 or u128?
What about a combinatorics explosion of (u128, u128, ...)?

It makes the problem a lot easier to check a specific const instantiation.

1 Like

I see that makes a lot of sense. Follow up question: I mostly found the compiler error message confusing. Do you know if anyone may have suggested improving the message to something like

consider adding where ... to the trait bound

Const generics treats values as types. You can think of the OP as being like this case: the complier can't prove the trait is implementated for all possible types as the parameter. Similarly to that example, if you can finagle your OP to have one unconditional implementation, it compiles.

The ability to recognize exhaustiveness is desired, but may not happen for some time.

1 Like