So my question is what is the difference between these two definitions? From what I've seen they should be the same. Also, this topic implies the same.
I'm not sure if this is a compiler bug or a subtle difference in the rules of where-clauses. In any event, I've implemented a minimum reproduction to show this isn't library-specific:
trait W {}
trait X {
type Y;
}
trait Z: X where Self::Y: W {}
struct A<T: Z>(T); // error!
The only kind of bounds that are implied via elaboration (that are “inherited” from a trait's declaration to its usage in other items’ bounds) are those which have exactly Self on the left side, or which use supertrait syntax, which is a shorthand for the same thing.
So, where Self::Error: Debug doesn't work the way you want, because the left side of the bound is Self::Error, not Self, but Self: Service<Bytes, Error: Debug> does fit that form, so it works.
Sometimes you need non-supertrait bounds at the definition site, for example because they're used in method signatures or default method bodies. But if you don't, one generally leaves them out;[1] you just have to repeat them everywhere anyway if you leave them in, and if there are sites that work without repeating them, your trait is probably more general without them.
If you're asking about the choice between an associated type bound that could be a supertrait bound or not specifically,[2] there are pros and cons to both. The supertrait form is implied everywhere else, so that's a lot less repeating of things. However, it is also a breaking change to remove an implied bound, so now you're stuck with that bound until the next major release (whereas you can remove non-implied bounds in the same major release). And if it's not required, it's still the case that your trait may be more general without the bound at all.
So if the bound is required, definitely go with the supertrait version so it is implied. Otherwise weigh the pros and cons.
Supertrait bound: implied everywhere, breaking change to remove the bound
where clause bound: have to repeat it everywhere (needed or not)
No bound: have to type it everywhere you need it, breaking change to add the bound