rust-lang / rust-lang/rust

Const generics do not accept exhaustive trait impls

Open
#146,962 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-coherence A-const-generics A-trait-system C-bug T-types
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.