OBVIOUS that Foo<int> is a subtype of Foo<T>
Perhaps, but not for me.
For me, a huge hole that breaks into the type system is simply unacceptable. If you want to drop the security type in such a window, I would rather use a dynamically typed language that was actually intended for this material.
The fact that arrays are covariant, although this is known to violate type safety, is bad enough, now you want to break it for everything?
This refers to the very heart of the type system. The entire type system performs program rejections. And due to Rhys's theorem, these rejected programs include perfectly well-typed, type-safe programs.
This is a huge cost. We remove expressiveness, preventing me from writing useful programs. To justify this cost, a type system is best paid most of the time. There are basically two ways to do this: render expressiveness at the level of the level that he selected at the program level and type of security.
The first is missing, simply because a system like C # is not powerful enough to allow me to express anything even remotely interesting. This leaves only the latter, and it is already on a rather shaky basis of null , covariant arrays, unlimited side effects, unsafe , etc. If you make generic types automatically covariant, you more or less completely select the latest security type information that remains.
There are only very few cases where S <: T ⇒ G<S> <: G<T> is actually type safe. ( IEnumerable is one such example.) And there are probably equally many cases where only S <: T ⇒ G<T> <: G<S> is type safe. ( IObservable , IComparer , IComparable , IEqualityComparer .) As a rule, neither G<S> <: G<T> nor G<T> <: G<S> are type safe.