"Trait bound not satisfied" when I'm requiring it to be satisfied

Here's an MWE to explain what I mean

trait Thingable<T> {}

trait Foo where
  Self::T: Thingable<i32>,
  i32: Thingable<Self::T>,
{
  type T;
}

struct Bar<F: Foo> (F::T);

in other words, I define a trait Foo with an associated type T, and bounds requiring that T: Thingable<i32> and vice-versa. So far so good. Then, I want to declare a struct with a bound that F: Foo, containing an F::T . But here I get

error[E0277]: the trait bound `i32: Thingable<<F as Foo>::T>` is not satisfied
note: required by a bound in `Foo`

but am I not asserting precisely that i32: Thingable<<F as Foo>::T>, by saying that F: Foo?? I'm very confused.

Supertrait bounds (bounds on Self, the implementor of the trait) are implied wherever the trait bound is met.[1] That is,

trait One: Two {}
// same as `trait One where Self: Two {}`

// Elsewhere
fn foo<T: One>()
// also implied: `T: Two`
{}

However, other bounds like your bound on i32 are not implied and must be repeated everywhere:

struct Bar<F: Foo> (F::T)
    where i32: Thingable<F::T>;

If the bound isn't required for the definition of the trait itself, I would remove it from the definition and only add it to places (like functions) that require it.

Related, not-implemented RFC.


  1. So are bound on associated types. ↩︎

4 Likes

Here's a workaround to impose the i32 bound via supertrait and associated type bounds. Makes the trait non-object safe though.

Here's another that's object safe.

2 Likes

This is also:

1 Like

Aha! That's a very succinct explanation, thank you. It's a shame that 2089-implied-bounds isn't merged yet.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.