Community
Participate
Working Groups
I20050214-0927 (jdt-core from 0215) When calling methods of generic types with a wildcard, the parameter types may have multiple wildcards (see also bug 83600). In that case, the eclipse compiler allows passing a List<+Number> to a parameter type that resolves to List<++Number>. A List<++Number> is not instantiable, though. Because +Number already has no lower bound, ++Number is not defined. Only the null type can have type A<++Number>. Consider the following example to clear things up: ---------- MultiWildcards.java --------- package generics.wildcards; import java.util.ArrayList; import java.util.List; public class MultiWildcards { void addAll(List<? extends Number> target, List<? extends Number> source) { target.addAll(source); } public static void main(String... args) { List<Integer> ints= new ArrayList<Integer>(); ints.add(3); List<Float> floats= new ArrayList<Float>(); floats.add(3f); new MultiWildcards().addAll(ints, floats); for (Integer integer : ints) { System.out.println(integer.intValue()); } } } ----------------------------------------- The example compiles with eclipse, but throws a CCE inside the for loop when ran. Javac correctly complains: --------- javac output --------- javac 1.5.0 [...]/generics/wildcards/MultiWildcards.java:9: cannot find symbol symbol : method addAll(java.util.List<capture of ? extends java.lang.Number>) location: interface java.util.List<capture of ? extends java.lang.Number> target.addAll(source); ^ 1 error -------------- It is questionable whether we should at all allow such double wildcards to appear in eclipse, as they make never sense / can be folded to one bound or the other. At least in content assist they make never sense, I will file another bug report for that. I believe the following rules apply: 1) A generic type with type bound ++T does not exist, since the lower bound of <no lower bound> is not defined (above case) 2) A generic type with type bound +-T exists, since the capture of -T is the capture of T. We can say that A<+-T> == A<+T>. 3) A generic type with type bound -+T does exist, it is the unbounded wildcard. We can say that A<-+T> == A<*> 4) A generic type with type bound --T does exist. We can say that A<--T> == A<-T> For 4), consider the following code: ----- super assignment allowed by javac ------- void assignAll(Class<? super Number> sup, Class<? extends Number> ext) { // Class<--Number> = Class<-Number> Class<? super Number> superSup= sup.getSuperclass(); // Class<-+Number> = Class<*> Class<?> superExt= ext.getSuperclass(); } --------- Eclipse allows the following to compile: --------- super assignment allowed by eclipse ----- void assignAll(Class<? extends Number> ext) { Class<? super Number> superExt= ext.getSuperclass(); } ---------------------------- javac complains: -------- javac output --------- [...]/generics/wildcards/MultiWildcards.java:30: incompatible types found : java.lang.Class<capture of ? super capture of ? extends java.lang.Number> required: java.lang.Class<? super java.lang.Number> Class<? super Number> superExt=ext.getSuperclass(); ----------------
likely related to our capture conversion support defficiencies.
With proper capture conversion implemented, we now issue (on 1st testcase): The method addAll(Collection<? extends capture-of ? extends Number>) in the type List<capture-of ? extends Number> is not applicable for the arguments (List<capture-of ? extends Number>) Added GenericTypeTest#test589.
Added GenericTypeTest#test590 for subsequent cases. Clearly the compiler error message reveals there is no such thing as wildcard collapsing. Unless this was spec'ed somewhere, we cannot alter this behavior. We now issue an error as well.
Fixed, along with capture change. This PR found that capture was missing on message send. Will be released along with changes for bug 84496
Released
Verified in I20050510-0010