Const generics do not accept exhaustive trait impls
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
pub struct Test<const FLAG: bool>;
pub trait Supertrait {}
pub trait Subtrait: Supertrait {}
impl Supertrait for Test<true> {}
impl Supertrait for Test<false> {}
impl<const FLAG: bool> Subtrait for Test<FLAG> {}
I expected the compiler to accept the implementation for Subtrait because Supertrait is implemented for every possible value of FLAG.
Instead, it cannot unify these implementations and gives an error:
error[E0277]: the trait bound `Test<FLAG>: Supertrait` is not satisfied
--> src/lib.rs:7:37
|
7 | impl<const FLAG: bool> Subtrait for Test<FLAG> {}
| ^^^^^^^^^^ the trait `Supertrait` is not implemented for `Test<FLAG>`
|
= help: the following other types implement trait `Supertrait`:
Test<false>
Test<true>
note: required by a bound in `Subtrait`
--> src/lib.rs:3:21
|
3 | pub trait Subtrait: Supertrait {}
| ^^^^^^^^^^ required by this bound in `Subtrait`
For more information about this error, try `rustc --explain E0277`.
Meta
rustc --version --verbose:
rustc 1.92.0-nightly (9f32ccf35 2025-09-21)
binary: rustc
commit-hash: 9f32ccf35fb877270bc44a86a126440f04d676d0
commit-date: 2025-09-21
host: x86_64-unknown-linux-gnu
release: 1.92.0-nightly
LLVM version: 21.1.1
Other remarks
This form of "exhaustive unification" is probably undesirable for things like integers (since even 256 trait implementations is quite a lot), but it is reasonable for boolean generics and will likely be desired as well once adt_const_params (tracked in #95174) is stable. In fact, there will probably be some desire to use ADT const generics to replace booleans for readability, so, this case doesn't seem too far-fetched.
Note that it is possible to make these cases much more complicated by adding two, three, or more boolean arguments, and those should be dealt with similarly.
Less-convoluted example
I'm personally interested in using this for the sake of avoiding macros in trait implementations, because it's immediately apparent why this is useful if you add associated types, for example:
pub trait Supertrait {
type Error: Default;
}
pub trait Subtrait: Supertrait {
fn do_thing(self) -> Result<Self, <Self as Supertrait>::Error>;
}
(this is still convoluted, but at least helpful to show the justification here)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by compiling the minimized example in src/lib.rs on the reported nightly compiler and reproduce the E0277 diagnostic. Trace how const generics and supertrait bounds are unified, then add coverage showing that exhaustive boolean implementations satisfy the bound; the reported example should compile while non-exhaustive cases remain rejected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100