Where clause in trait definition must be copied to where the trait is used?

This is a case of non-supertrait bounds not being elaborated elsewhere. That is, here:

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:

// Inline associated type bound  vvvvvvvvvvvvvvvvvvvvvvvvvv
trait DeserRefer: for<'de> Refer<Ref<'de>: Deserialize<'de>> {}

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

  • Remove the bound
    • But then can never add it back, implied or not
  • Make it implied[2]
    • But then can never remove it or make it non-implied

(where "can" and "can never" are short for "non-breaking change" and "breaking change").


  1. Despite the jargon, "supertrait" bounds can also be lifetime bounds. ↩︎

  2. as far as is possible in the language ↩︎

6 Likes