| Summary: | [1.5][compiler] Compiler error on sorting generics with java.util.Collections | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Jan Hoppe <jan.hoppe> | ||||
| Component: | Core | Assignee: | Srikanth Sankaran <srikanth_sankaran> | ||||
| Status: | CLOSED WONTFIX | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P3 | CC: | deepak, Olivier_Thomann, philippe_mulet, satyam.kandula, srikanth_sankaran | ||||
| Version: | 3.5 | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | PC | ||||||
| OS: | Windows XP | ||||||
| Whiteboard: | stalebug | ||||||
| Attachments: |
|
||||||
Compiles fine with javac 1.6 and 7.0.
With 1.6_14 I get:
X.java:10: warning: [unchecked] unchecked conversion
found : java.util.Vector
required: java.util.List<T>
Collections.sort(children, comparator);
^
X.java:10: warning: [unchecked] unchecked method invocation: <T>sort(java.util.List<T>,java.util.Comparator<? super T>) in java.util.Collections is applied to (java.util.Vector,java.util.Comparator<capture#31 of ? extends X.A>)
Collections.sort(children, comparator);
^
I would think this code should indeed be accepted. Smaller testcase
import java.util.Comparator;
class X {
<T> void sort(Comparator<? super T> c) {}
<T> void sort2(Comparator<? extends T> c) {}
void a(Comparator<?> a) {
sort(a); // eclipse reports an error that javac doesn't
}
void b(Comparator<?> b) {
sort2(b); // accepted by both
}
}
in 3.4.2, only the sort2 call was an error (its not in javac)
now both the sort & sort2 calls cause errors (javac reports a warning on sort)
import java.util.*;
class Y {
<T> void sort(List<T> list, Comparator<? super T> c) {}
<T> void sort2(Comparator<? super T> c) {}
void a(Vector v, Comparator<?> c) {
sort(v, c);
sort2(c);
}
}
in 3.4.2, we use to infer sort(List#RAW, Comparator#RAW) sort2(Comparator<? super Object>) but now we infer sort(List<Object>, Comparator<? super Object>) sort2(Comparator<? super Object>) Philippe - we differ from javac in all 3 sends of accept1(Comparator<? super T>)
Should Comparator<? super T> be converted to Comparator<?> instead ?
import java.util.*;
class Y {
<T> void accept1(Comparator<? super T> c) {}
void accept2(Comparator<?> c) {}
void accept3(Comparator<? extends Object> c) {}
void fail(Comparator<? super Object> c) {}
void a(Comparator<? extends Object> c) {
accept1(c); // eclipse fails, we infer Comparator<? super Object>
accept2(c);
accept3(c);
fail(c); // javac rejects since Comparator<? super Object> is not a match
}
void b(Comparator<?> c) {
accept1(c); // eclipse fails, we infer Comparator<? super Object>
accept2(c);
accept3(c);
fail(c); // javac rejects since Comparator<? super Object> is not a match
}
void c(Comparator<? extends Y> c) {
accept1(c); // eclipse fails, we infer Comparator<? super Object>
accept2(c);
accept3(c);
fail(c); // javac rejects since Comparator<? super Object> is not a match
}
}
Re: testcase in comment 0 We do no longer trigger raw conversion for unchecked invocations, as we used to in 3.4.x; and thus matches both the spec expectation (15.12.2.6) and javac, in general. We do indeed infer #sort(List<Oject>, Comparator<? super Object>); which is also consistent with javac (can be proven by a variation on the testcase, by checking the error message when unable to convert from T=Object to int : import java.util.Comparator; import java.util.List; import java.util.Vector; public class X { class A { } void compare2() { Vector children = new Vector(); Comparator<? extends A> comparator = null; int i = sort2(children, comparator); } static <T> T sort2(List<T> list, Comparator<? super T> c) { return list.get(0); } } We do produce an error during substituted method applicability check, where the compiler does not consider that: Comparator<capture-of-? extends A> is a super type of Comparator<? super Object> which seems to be a valid diagnosis, as can be checked by simpler testcase, where both javac and Eclipse do complain: import java.util.*; public class X { class A { } void foo(Comparator<? super Object> cso) { } void bar() { Comparator<? extends A> comparator = null; foo(comparator); } } erratum: > ... Comparator<capture-of-? extends A> is a super type of Comparator<? super Object> should read: > ... Comparator<capture-of-? extends A> is compatible with Comparator<? super Object> It almost feels that in presence of unchecked method invocation, javac would bypass the applicability check... I know they do bypass the bound checks (against the spec already). Actually, it only bypasses the check when the argument type contains the offending unchecked type param:
e.g. complains for:
public class X {
class A {}
<T> void foo(List<T> ls, Comparator<? super Object> cso) {}
void bar() {
Comparator<? extends A> comparator = null;
foo(new Vector(), comparator);
}
}
e.g. does NOT complain for (only unchecked warnings) :
public class X {
class A {}
<T> void foo(List<T> ls, Comparator<? super T> cst) {}
void bar() {
Comparator<? extends A> comparator = null;
foo(new Vector(), comparator);
}
}
Targetting 3.6. If a fix is found in time for 3.5.2, we might backport it. Here's another simple test case that I believe is related to this bug.
The following works in Eclipse 3.4 but not in 3.5
--------------------------------------
public class Main {
class Foo implements Comparable {
@Override
public int compareTo(Object o) {
return 0;
}
}
public static void main(String[] args) {
List<Foo> foo = new ArrayList<Foo>();
Foo bar = Collections.max(foo); // Error in 3.5
}
}
--------------------------------------
Changing Foo to the following appeases 3.5 and makes the error go away
class Foo implements Comparable<Object> {
...
}
(In reply to comment #12) > Here's another simple test case that I believe is related to this bug. > > The following works in Eclipse 3.4 but not in 3.5 > -------------------------------------- > public class Main { > class Foo implements Comparable { > @Override > public int compareTo(Object o) { > return 0; > } > } > > public static void main(String[] args) { > List<Foo> foo = new ArrayList<Foo>(); > Foo bar = Collections.max(foo); // Error in 3.5 > } > } > -------------------------------------- This is same as bug#277643 fixed and released into 3.5.2 The issue in comment#0 is still open and is under investigation. (In reply to comment #11) > Targetting 3.6. If a fix is found in time for 3.5.2, we might backport it. Going to require more time to analyze this. At least the initial analysis per earlier comments points to a probable javac issue. Need to retarget to post 3.6 Retargetting to 3.7. If resolution found in time for 3.6.2, will make it available for 3.6.2. If we want to address it for 3.7, it has to be done for RC1. Sorry, didn't have time to look into this yet as most of the cycles in the last few months went into Java 7 work. Now it is too late in the game for 3.7. Postponed to 3.8 Sorry, need to postpone this as I don't have time in the 3.8 time frame. Problem remains in 4.4M6... This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie. |
Created attachment 135747 [details] Sample Project showing error in synthetic class Build ID: I20090503-1800 Steps To Reproduce: 1.Create class listed below 2.Works on 3.4.2 3.Error on 3.5M7 (The method sort(List<T>, Comparator<? super T>) in the type Collections is not applicable for the arguments (Vector, Comparator<capture#1-of ? extends ComperatorCheck.A>) ComperatorCheck.java /ErrorChecker/src line 30 Java Problem This one blocks usage of 3.5 in our Company More information: public class ComperatorCheck { class A { } void compare() { Vector children = new Vector(); Comparator<? extends A> comparator = null; Collections.sort(children, comparator); } }