I wrote up this short example, which doesn't compile:
use serde::Deserialize;
trait Refer {
type Ref<'a>;
}
// example
impl Refer for String {
type Ref<'a> = &'a str;
}
trait DeserRefer: Refer
where for<'de> Self::Ref<'de>: Deserialize<'de> {}
impl<T: Refer> DeserRefer for T
where for<'de> Self::Ref<'de>: Deserialize<'de> {}
fn test<T: DeserRefer>(t: T) {
}
The issue in this example is that, despite the DeserRefer requiring that the implementor's Ref implement Deserialize, this requirement is for some reason repeated for test()- i.e. the where clause in the definition of DeserRefer needs to be repeated in the declaration of test(). This is a different behavior than I would expect- I would never expect the compiler to require that test() have a where clause, in addition to the constraint placed on T. Shouldn't the constraint T: DeserRefer be enough? Is this a trait solver bug?
trait DeserRefer: Refer
where for<'de> Self::Ref<'de>: Deserialize<'de> {}
The where clause is not considered supertrait bound (a bound on Self).[1]
If you don't have to worry about MSRV, we recently got the ability to make bounds on associated types of Self into bounds on Self, thus making them supertrait bounds which are implied elsewhere:
A few words about "well why didn't it just do that for me?!".
One (very large) consideration with implied bounds, such as supertrait bounds which you don't have to repeat elsewhere, is that removing the bound from the trait becomes a breaking change. In contrast, with your OP, the trait author could remove the bound without breaking downstream code.
Therefore, implied bounds is not something you always want, and not something that can be inflicted on the ecosystem in good conscious (e.g. automatically converting all pre-existing, non-supertrait associated type bounds involving Self to be supertrait bounds). Instead it should be something the author opts into.
Given a non-implied bound on a trait definition, the trait can