interface List<E> {}
class Test {
<T> void merge(List<T> l1, List<T> l2) {}
void test(List<? extends Test> list) {
merge(list, list);
}
}
The compiler says:
../Test.java:6: <T>merge(List<T>,List<T>) in Test cannot be applied to
(List<capture of ? extends Test>,List<capture of ? extends Test>)
merge(list, list);
^
1 error
This is confusing because how is List<capture of ? extends Test> different
from List<capture of ? extends Test>?
I'm trying to improve this diagnostic and am considering this error message:
../Test.java:6: <T>merge(List<T>,List<T>) in Test cannot be applied to
(List<E#0 (capture of ? extends Test)>,List<E#1 (capture of ? extends Test)>)
merge(list, list);
^
1 error
It should now be clear that List<E#0 (capture of ? extends Test)>
is different from List<E#1 (capture of ? extends Test)>.
UPDATE: what I would really like is something along these lines:
../Test.java:6: <T>merge(List<T>,List<T>) in Test cannot be applied to (List<E#0>,List<E#1>)
where E#0 and E#1 are type variables
and E#0 extends Test (capture of ? extends Test)
and E#1 extends Test (capture of ? extends Test)
merge(list, list);
^
1 error
However, I think this would require too much restructuring and prefer to defer this to Dolphin. The above is a fairly simple change to the compiler and is possible for Mustang.
Posted by David Hall on August 31, 2005 at 10:12 AM PDT #
Posted by Eugene Vigdorchik on August 31, 2005 at 11:02 AM PDT #
Posted by Eamonn McManus on September 07, 2005 at 05:44 AM PDT #
../Test.java:6: <T>merge(List<T>,List<T>) in Test cannot be applied to
(List<T#0 (capture of ? extends Test)>,List<T#1 (capture of ? extends Test)>)
merge(list, list);
^
1 error
Like Eamonn, i think an error message without
parenthesis is more readable.
For me, the wilcard signe (?) must be
numbered not the capture.
So <tt>capture of ?1 extends Test</tt>
have my vote.
I think the version for dolphin is too long and don't explain more that the mustang one.
A 4 lines error message scary me more than
it inform me.
Ok, it's less than a regular G++ message
about template but that is not a reason.
Posted by Rémi Forax on September 07, 2005 at 02:24 PM PDT #
What I find most confusing about this example is that it <em>isn't</em> really an error. The same list is passed to merge and therefore it must have the same type!
Therefore my ideal would be for this example to pass! However there are probably other examples that should genuinely fail. Therefore any error message that adds a number to indicate that multiple captures are going on would help. I suggest something like:
../Test.java:6: <T>merge(List<T>,List<T>) in Test cannot be applied to
(List<capture 1 of (? extends Test)>,List<capture 2 of (? extends Test)>). Note: the captures are to the type checker different types even if they are in some way related (e.g. the same type).
merge(list, list);
^
1 error
The main difference c.f. your original is that I have used English instead of symbols and added a clarifying note to the message.
PS I would encourage you to improve the error messages, it is an important area and one of the reasons I dislike C++ templates are that the error messages are hard to follow.
Posted by Howard Lovatt on September 20, 2005 at 08:47 PM PDT #
../Test.java:6: <T>merge(List<T>,List<T>) in Test cannot be applied to
(List<capture#0 of ? extends Test>,List<capture#1 of ? extends Test>)
merge(list, list);
^
1 error
Posted by Peter Ahé on September 20, 2005 at 09:09 PM PDT #
../Test.java:6: [T]merge(List[T],List[T]) in Test cannot be applied to (List[capture 1 of (? extends Test)],List[capture 2 of (? extends Test)]). Note: the captures are to the type checker different types even if they are in some way related (e.g. the same type).PS I substituted square braces for angle braces because it won't post with angle braces even if I use HTML escapes!
Posted by Howard Lovatt on September 20, 2005 at 09:21 PM PDT #