| Summary: | Eclipse allows implicit conversion from T<U> to T<? extends U<?>> in method invocation context | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Benjamin Horstman <bhorstman> | ||||
| Component: | Core | Assignee: | JDT-Core-Inbox <jdt-core-inbox> | ||||
| Status: | CLOSED WONTFIX | QA Contact: | Stephan Herrmann <stephan.herrmann> | ||||
| Severity: | minor | ||||||
| Priority: | P3 | CC: | hudsonr, jarthana, markus.kell.r, sasikanth.bharadwaj, sebastian.zarnekow, stephan.herrmann | ||||
| Version: | 4.4.2 | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | PC | ||||||
| OS: | All | ||||||
| Whiteboard: | stalebug | ||||||
| Attachments: |
|
||||||
Get rid of your raw types (by adding wildcards) and you'll see that javac, too, accepts the variant using the helper method :) <rant> I personally give no priority anymore to adjusting ecj to javac wrt handling of raw types. We've already added more than enough bug-compatibility tweaks in this area. Maybe it's even one of those tweaks that in this particular situation makes ecj answer wrongly. I don't know. But I know that mimicking buggy javac wrt raw types is a battle we can never win. OTOH, raw types were deprecated right when they were introduced in Java 5, 10 years ago. </rant> I might reconsider if s.o. provides clear JLS-based reasoning, why the error should be reported. Yes, the best solution is not to use raw types. The guilty parties have been alerted :) It's already fixed for us, I'm just reporting the (very few!) hiccups upgrading to Java 8. I only reported here because it seemed like eclipse was inconsistent with itself between the two cases. I am not a JLS expert, but I was also not able to determine the correct behavior using the spec. If you think it's not worth fixing, it's fine with me. Here's a related case where casting conversion fails with javac (6,7,8) but succeeds with ECJ:
import java.util.ArrayList;
import java.util.Collection;
public class Test {
public Object foo() {
Class<ArrayList> cl = ArrayList.class; // type contains raw type
// return (Class<?>) cl; // OK
// return (Class<? extends ArrayList>) cl; // OK
// return (Class<? extends Collection<?>>) cl; // javac doesn't compile
return (Class<? extends ArrayList<?>>) cl; // javac doesn't compile
}
}
javac full version "1.8.0_60-ea-b12"
C:\...\zz1.7\src\Test.java:10: error: incompatible types: Class<ArrayList> cannot be converted to Class<? extends ArrayList<?>>
return (Class<? extends ArrayList<?>>) cl; // javac doesn't compile
^
1 error
(In reply to Markus Keller from comment #3) > Class<ArrayList> cl = ArrayList.class; // type contains raw type reminds me of the question: what to recommend to users in order to avoid raw types also in situations like this? From the example I get the impression, javac won't even let you create a "Class<? extends ArrayList<?>>" value from a class literal? Bad ... Still, we should come to our own conclusion whether or not these examples are legal. Yeah, as you've probably read between the lines in comment 3, I didn't come to a conclusion whether this should be allowed or not. OTOH, I'm certain that JLS8 is still fundamentally inconsistent about raw types: - 4.8 says: "The use of raw types is allowed only as a concession to compatibility of legacy code." - 15.8.2 says: "The type of C.class, where C is the name of a class, interface, or array type (§4.3), is Class<C>." => The only conclusion would be that the class literal "ArrayList.class" is not allowed in non-legacy code. But that doesn't make much sense. JDK bugs (with conclusions: "don't know what to do"): https://bugs.openjdk.java.net/browse/JDK-6184881 https://bugs.openjdk.java.net/browse/JDK-6209029 (In reply to Markus Keller from comment #5) > OTOH, I'm certain that JLS8 is still fundamentally inconsistent about raw > types: > - 4.8 says: "The use of raw types is allowed only as a concession to > compatibility of legacy code." > - 15.8.2 says: "The type of C.class, where C is the name of a class, > interface, or array type (§4.3), is Class<C>." > => The only conclusion would be that the class literal "ArrayList.class" is > not allowed in non-legacy code. But that doesn't make much sense. I fully agree. > JDK bugs (with conclusions: "don't know what to do"): > https://bugs.openjdk.java.net/browse/JDK-6184881 > https://bugs.openjdk.java.net/browse/JDK-6209029 thanks for digging these out. 11 years and no action, *but* a recent supportive comment ... should we hope? 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. As such, we're closing this bug. If you have further information on the current state of the bug, please add it and reopen this bug. 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. (In reply to Stephan Herrmann from comment #6) > (In reply to Markus Keller from comment #5) > > OTOH, I'm certain that JLS8 is still fundamentally inconsistent about raw > > types: > > - 4.8 says: "The use of raw types is allowed only as a concession to > > compatibility of legacy code." > > - 15.8.2 says: "The type of C.class, where C is the name of a class, > > interface, or array type (§4.3), is Class<C>." > > => The only conclusion would be that the class literal "ArrayList.class" is > > not allowed in non-legacy code. But that doesn't make much sense. > > I fully agree. > > > JDK bugs (with conclusions: "don't know what to do"): > > https://bugs.openjdk.java.net/browse/JDK-6184881 > > https://bugs.openjdk.java.net/browse/JDK-6209029 > > thanks for digging these out. 11 years and no action, *but* a recent > supportive comment ... should we hope? Nope, those JDK bugs are dead. Hence genie's decision to close our bugs was a good one. |
Created attachment 252143 [details] I expect that eclipse should report an error in both functions Conversion from T<U> to T<U<?>> is disallowed. However, when an intermediate function (such as guava's Lists.newArrayList) is used, eclipse allows it. Javac 6,8,9 reports an error in both cases. See attached example. Output from javac: bhorstman@bhorstman-Precision-WorkStation-T3500:~$ ~/jdk/jdk1.6.0_45/bin/javac ~/Test2.java ^[[A/home/bhorstman/Test2.java:7: incompatible types found : java.util.ArrayList<Test2.GenericClass> required: java.util.List<Test2.GenericClass<?>> return newArrayList(set); ^ /home/bhorstman/Test2.java:11: incompatible types found : java.lang.Iterable<Test2.GenericClass> required: java.util.List<Test2.GenericClass<?>> List<GenericClass<?>> rv = set; //compile error in both ^ 2 errors bhorstman@bhorstman-Precision-WorkStation-T3500:~$ ~/jdk/jdk1.8.0_20/bin/javac -Xdiags:verbose ~/Test2.java ^[[A/home/bhorstman/Test2.java:7: error: incompatible types: cannot infer type-variable(s) E return newArrayList(set); ^ (argument mismatch; Iterable<GenericClass> cannot be converted to Iterable<? extends GenericClass<?>>) where E is a type-variable: E extends Object declared in method <E>newArrayList(Iterable<? extends E>) /home/bhorstman/Test2.java:11: error: incompatible types: Iterable<GenericClass> cannot be converted to List<GenericClass<?>> List<GenericClass<?>> rv = set; //compile error in both ^ 2 errors bhorstman@bhorstman-Precision-WorkStation-T3500:~$ ~/jdk/jdk1.9.0/bin/javac -Xdiags:verbose ~/Test2.java /home/bhorstman/Test2.java:7: error: incompatible types: cannot infer type-variable(s) E return newArrayList(set); ^ (argument mismatch; Iterable<GenericClass> cannot be converted to Iterable<? extends GenericClass<?>>) where E is a type-variable: E extends Object declared in method <E>newArrayList(Iterable<? extends E>) /home/bhorstman/Test2.java:11: error: incompatible types: Iterable<GenericClass> cannot be converted to List<GenericClass<?>> List<GenericClass<?>> rv = set; //compile error in both ^ 2 errors