Ahh I think I know where my mistake lies. First I thought it should work because I assumed it's completely irrelevant in this case what U actually is when I say Gat<U> = T but it could also be for example that there are bounds at the GAT in the trait where U is involved and when that's the case it would of course be necessary to actually know U!
Yes, it's not clear what U actually is but my assumption - according to my initial example - was that the question what U is doesn't even arise here but there can of course be cases when the concrete type you assign in an impl to Gat depends on U in one way or another and then you have to know U of course.
Side question: Might this work in the future when we maybe get fully-fledged HKTs?
More precisely, for every generic parameter T of a struct, the compiler wants to determine if T is invariant, covariant, or contravariant in Struct<.., T, ..>.[1] If it can't do that, then T must be constrained -- able to be determined by the other (constrained) parameters.
Note that the RFC calls out the "constrained associated type" case as an exception. Those are, in fact, bivariant! (Though I've never seen it come up in "real" code.) I think it would not be observable if you couldn't implement traits differently for super-and-sub types, but the current plan is to keep accepting that, despite the future compat warning. The fact that it is observable may have been an oversight.[4]
There are two definitions of bivariance in common use. One is "covariant and contravariant". The other is "can coerce to anything". Rust uses the latter. ↩︎