- Notifications
You must be signed in to change notification settings - Fork 13.2k
Description
Bug Report
🔎 Search Terms
contravariance bypass inheritance variance annotation
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about variance.
⏯ Playground Link
Playground link with relevant code
💻 Code
In this example we use contravariance to make Comparator<Animal> assignable to Comparator<Dog> : something than can compare animals can compare dogs.
classAnimal{}classDogextendsAnimal{wouf=true;}classComparator<inT>{publiccompare(a: T,b: T): boolean{returntrue;}}classDogComparatorextendsComparator<Dog>{compareDogs=true;}// [ok] an Animal comparator can compare Dogs, so then it is assignable to Comparator<Dog>constokCompareDogs: Comparator<Dog>=newComparator<Animal>();// [error as expected] a Dog comparator cannot compare Animals as it may require specific props of Dog for comparison constokCompareAnimals: Comparator<Animal>=newComparator<Dog>();// [should be an error] It should be the same here, the fact that DogComparator is a subclass of Comparator<Dog> should not bypass contravariance// DogComparator which extends Comparator<Dog> is still not a subclass of Comparator<Animal> as Animal is not a subclass of DogconstnokCompareAnimals: Comparator<Animal>=newDogComparator();🙁 Actual behavior
The following line is accepted by the compiler:
constnokCompareAnimals: Comparator<Animal>=newDogComparator();I think the problem is that as DogComparator is a subclass of Comparator, the compiler only checks for(a: Dog, b: Dog) => boolean to be assignable to (a: Animal, b: Animal) => void, regardless of contravariance annotation put on the generic type.
🙂 Expected behavior
The nok line above should give a compilation error as contravariance on Comparator's generic parameter should prevent DogComparator (which extends Comparator<Dog>) from being treated as a Comparator<Animal>.
Even if (a: Dog, b: Dog) => boolean is assignable to (a: Animal, b: Animal) => void, there should be a second contraint to check if Animal is a subtype of Dog (which will give the error) because of contravariance on the generic parameter.
For information this is the case in Kotlin: see this playground sample
Thanks 😃