rustc fails to see a bound that is present, but also requires that the bound not be present

cc670b8
Opened by James Kay at 2024-12-21 05:02:42

In certain cases, rustc will emit an error message on what appears to be valid code, claiming that

  • a bound that is present is not present, and must be present
  • but the bound is present and must not be present

Here is a MWE (or playground):

trait Foo<T> { type Quux; }
trait Bar<B> {
    type Baz;
    fn arthur() where B: Foo<Self::Baz>, B::Quux: Send;
}
impl<B> Bar<B> for () {
    type Baz = ();
    fn arthur() where B: Foo<()>, B::Quux: Send { }
}

This produces the pair of errors:

rustc 1.16.0 (30cf806ef 2017-03-10)
error[E0277]: the trait bound `B: Foo<()>` is not satisfied
 --> <anon>:8:5
  |
8 |     fn arthur() where B: Foo<()>, B::Quux: Send { }
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo<()>` is not implemented for `B`
  |
  = help: consider adding a `where B: Foo<()>` bound

error[E0276]: impl has stricter requirements than trait
 --> <anon>:8:5
  |
4 |     fn arthur() where B: Foo<Self::Baz>, B::Quux: Send;
  |     --------------------------------------------------- definition of `arthur` from trait
...
8 |     fn arthur() where B: Foo<()>, B::Quux: Send { }
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `B: Foo<()>`

error: aborting due to 2 previous errors
  1. It's interesting to note that the bound B::Quux: Send is an integral part of this MWE: removing it bypasses the error.

    James Kay at 2017-04-06 18:20:32

  2. afaict this is caused by our current approach to param env normalization, see https://github.com/rust-lang/rust/blob/c225c45bce099e4ff6c61c73a425326d1625ed2f/compiler/rustc_trait_selection/src/traits/mod.rs#L328-L345

    fixed in the new solver because we defer projection equality there, so the unnormalized B: Foo<Self::Baz> candidate now applies to the B: Foo<()> goal.

    lcnr at 2023-11-13 11:43:56