Description
Here's a very simple example:
extension type ET(int it) {}
extension type ETnum(int it) implements num {}
void m1(int? a, ET b) {
a == b;
b == a;
}
void m2(int? a, ETnum b) {
a == b;
b == a;
}
An ET
can be equal to an int?
, and vice versa. An ETnum
can be equal to a int?
, and vice versa. It seems like they should be considered "related."
Similarly an extension type should be considered "related" to other extension types that it "implements."
One other big lint rule that this affects is collection_methods_unrelated_type
:
extension type ET(int it) {}
extension type ETnum(int it) implements num {}
bool m1(List<int> list, ET a) => list.contains(a);
bool m2(List<ET> list, int a) => list.contains(a);
bool m3(List<int> list, ETnum a) => list.contains(a);
bool m4(List<ETnum> list, int a) => list.contains(a);
Should all of the code here be allowed? I think so...
So more formally, given a type T and an extension type V1 declared as extension type V1(T it) implements V2, V3, ...
:
- V1 is related to T.
- T is related to V1.
- V1 is related to V2, etc.
- V2, etc. are related to V1.
But there might be something more necessary, like "V1 is related to any type which T is related to." Then if V1 is an extension type on int, it is related to num.
I'll note that the algorithm for "relatedness" is not super well-defined, and is pretty ad hoc, but these are important linter rules, and the existing relatedness algorithm has gotten us very far.