Bug 85281 - [1.5][compiler] A<++Element> should not be assignable a A<+Element>
Summary: [1.5][compiler] A<++Element> should not be assignable a A<+Element>
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC All
: P3 normal (vote)
Target Milestone: 3.1 M7   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-02-15 11:07 EST by Tom Hofmann CLA
Modified: 2005-05-11 10:38 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Hofmann CLA 2005-02-15 11:07:34 EST
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();
----------------
Comment 1 Philipe Mulet CLA 2005-03-24 05:39:41 EST
likely related to our capture conversion support defficiencies.
Comment 2 Philipe Mulet CLA 2005-04-12 06:32:24 EDT
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.
Comment 3 Philipe Mulet CLA 2005-04-12 06:54:52 EDT
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.
Comment 4 Philipe Mulet CLA 2005-04-12 08:03:09 EDT
Fixed, along with capture change. 
This PR found that capture was missing on message send.
Will be released along with changes for bug 84496
Comment 5 Philipe Mulet CLA 2005-04-21 09:10:45 EDT
Released
Comment 6 Olivier Thomann CLA 2005-05-11 10:38:19 EDT
Verified in I20050510-0010