generic types have special rules for type compatibility, referred to as covariance and contravariance. These rules determine whether references of certain generic types are implicitly convertible to one another when implicit conversions exist between their type arguments.
Key: these apply only to generic types. Summary: covariance is when there exists a conversion for the generic (templated) type in the same direction as the type argument, ie GenericT<out Derived> can be converted to GenericT<Base>.
Contravariance is the opposite direction ie GenericT<in Derived> can be converted to GenericT<Base> .
I don't know how well the compiler enforces this. In the shape comparer example, does it know whether the conversion is valid? Experiment.