I use Dart2JS Compiler version 1.0.0_r30798 (STABLE).
Sample code (only for introducing problem):
The real code here (now corrected for dart2js behavior): https://github.com/mezoni/queries/blob/master/lib/src/queries/lookup.dart
This is a part of Queryable collections for Dart language.
class ILookup<TKey, TElement> implements IEnumerable<IGrouping<TKey, TElement>> {
}
class Lookup<TKey, TElement> extends Object with Enumerable implements ILookup<TKey, TElement> {
}
class IEnumerable<T> implements HasIterator<T> {
}
class HasIterator<T> {
}
class IGrouping<TKey, TElement> implements IEnumerable<TKey> {
}
class Enumerable<T> implements IEnumerable<T> {
}
void main() {
var obj = new Lookup();
print(obj);
}
This code generates the following error of Google Dart dart2js Compiler:
Internal Error: Inheritance of the same class with different type arguments is not
supported: Both HasIterator<dynamic> and HasIterator<IGrouping<TKey, TElement>> are
supertypes of Lookup<TKey, TElement>.
class Lookup<TKey, TElement> extends Object with Enumerable implements ILookup<TKey,
TElement> {
^^^^^
Error: Compilation failed.
That is, the dart2js
compiler cannot compile this code.
So, I cannot understand: " Is this bug, feature or limitation?".
Answer from Dart Team is very well.
"The VM behavior is correct, and dart2js isn't implementing it yet."
https://code.google.com/p/dart/issues/detail?id=16047#c5
Also answer from Gilad Bracha.
"FWIW, the spec does not have such a restriction" (RE: class implements an interface with two different type parameters).
https://code.google.com/p/dart/issues/detail?id=14729#c2
Also very well mentioned:
"Unfortunately this is an intentional restriction in dart2js for now. Implementing the same interface with different type arguments has never really worked, so we felt very uncomfortable having people depend on the broken behavior."
https://code.google.com/p/dart/issues/detail?id=14729#c3
This answer fully fits in that the sample code in original question correct and it cannot be compiled currently via dart2js.
P.S.
My thoughts (my jumpers):
I think this problem can be solved in the Dart2JS compiler via better testing of type compatibility but not only via testing the equality of classes.
I think that in this case
HasIterator<dynamic>
andHasIterator<IGrouping<TKey, TElement>>
is not the same types (even they the same classes) because they both just implicitly specifies lower and upper bounds ofTElement
parameter ofHasIterator<TElement>
.In practice this is more complex that I can explain here but I can add the following.
They not the same types because this expression is true:
They not conflicts (but implicitly specifies lower and upper bounds) because one from the following expressions is true.
Is our case (implicit) lower bound is
dynamic
and (implicit) upperbound
is<IGrouping<TKey, TElement>
.The
implicit
term means onlyresolved at compile time
.This means that one from them is a subtype of another and compiler must allow both of them in declaration. And in type annotations the compiler must tests parameters on compatibility with both of them (including other super interfaces).
If Dart2JS will test supertypes more thoroughly it can bypass around this problem.
I not want here give sample how this is possible but I think developers know how to solve this problem.