Community
Participate
Working Groups
public final void addShortDescription(Object object, StringBuffer buf) { try { W_Description wdescription = get(W_Description.class,object); // GIVES AN ERROR // Type mismatch: cannot convert from WrapperLogic to W_Description wdescription.setVerbosity(Verbosity.terse); wdescription.setIncludeSubDescriptions(false); wdescription.getDescription(buf); } catch (Exception e) { } } public <T, W extends WrapperLogic<? super T>> W get(Class<W> wrapperClass, T entity) { return getLogicFactory().get(wrapperClass, entity); } It seems the compiler is unable to recognise that the get method return a W. The code compiles fine with ant, and it works in Eclipse 3.4 and below.
How can we reproduce this without the source for WrapperLogic & W_Description ? Please attach a complete reproduceable testcase.
Hi, Sorry here you go, should illustrate the problem :) public class Test { public final void addShortDescription(Object object, StringBuffer buf) { try { W_Description wdescription = get(W_Description.class, object); // ERROR Type mismatch: cannot convert from Test.WrapperLogic to Test.W_Description } catch (Exception e) { } } public abstract class W_Description<WRAPPED> extends WrapperLogic<WRAPPED> { } public <T, W extends WrapperLogic<? super T>> W get(Class<W> wrapperClass, T entity) { return getLogicFactory().get(wrapperClass, entity); } private LogicFactory logicFactory; public final LogicFactory getLogicFactory() { return logicFactory; } public interface LogicFactory { <LOGIC extends Logic> LOGIC get(Class<LOGIC> logicClass); <WRAPPED, WRAPPER_LOGIC extends WrapperLogic<? super WRAPPED>> WRAPPER_LOGIC get(Class<WRAPPER_LOGIC> wrapperLogicClass, WRAPPED entityToWrap); } public abstract class WrapperLogic<WRAPPED> extends AbstractLogic implements Wrapper<WRAPPED> { } public abstract class AbstractLogic { } public interface Wrapper<WRAPPED> { WRAPPED getWrapped(); } public abstract class Logic extends AbstractLogic { } }
Created attachment 137110 [details] Test case for the error Now as an attachment :o)
Simpler case : class Test { A a = get(A.class); <T, U extends B<? super T>> U get(Class<U> c) { return null; } } class A<T> extends B<T> {} class B<U> {} javac issues an unchecked method invocation: method get in class Test is applied to given types required: java.lang.Class<U> found: java.lang.Class<A> In 3.4.x we do not report an error or an unchecked method invocation. In 3.5RC2, we report both an unchecked method invocation & type mismatch error: cannot convert from B to A
Philippe - can you explain this code in MesssageSend.resolveType() ? TypeBinding returnType; if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) { returnType = this.binding.original().returnType; if (returnType != null) { returnType = scope.environment().convertToRawType(returnType.erasure(), true); } } else { returnType = this.binding.returnType; if (returnType != null) { returnType = returnType.capture(scope, this.sourceEnd); } } this.resolvedType = returnType; When the inferred return type is already a raw type, why ignore it & use the original's return type ?
JLS 15.12.2.6 requires to surface the original method type in raw form, as opposed to reusing the inferred return type (in raw form) (which javac is using by mistake). This is why though you inferred A, you have to surface B for unchecked invocations.
Soren, we believe this is a bug in javac as Philippe described. Closing as NOT_ECLIPSE
(In reply to comment #7) > Soren, we believe this is a bug in javac as Philippe described. > > Closing as NOT_ECLIPSE > It might well be that the spec is right, and javac is wrong, but is it possible to make a flag to enable the old stlye ? From my point of view the old style seems to make more sense, you have the information about the class to return, why throw that away ? We can't be the only ones that have used this "feature" in 3.4, and now it's an error. Seems to me that perhaps alot of people wil complain about this :o(
You do not have to reopen the bug to add a comment. It wasn't a 'feature' or 'style' in 3.4 - it was a bug that has been fixed. And we do not get to pick and choose which aspects of the spec we follow. > From my point of view the old style seems to make more sense, you have the > information about the class to return, why throw that away ? Because its a raw type. If you replace the raw type reference, you will not see this problem.
Verified for 3.5RC3 using I20090526-2000.
*** Bug 280054 has been marked as a duplicate of this bug. ***
*** Bug 280809 has been marked as a duplicate of this bug. ***
(In reply to comment #9) > And we do not get to pick and choose which aspects of the spec we follow. Has anyone contacted Sun on this? I'm not sure how the JLS is managed, but this might be one of those areas where the spec needs to be revised to match the popular implementations (including javac).
(In reply to comment #8) > We can't be the only ones that have used this "feature" in 3.4, and now it's an > error. Seems to me that perhaps alot of people wil complain about this :o( You are not alone. Ran into the problem on the first project I tried to checkout into 3.5RC4.
(In reply to comment #9) > If you replace the raw type reference, you will not see > this problem. Could you illustrate how to do this with the example: package bugs.eclipse; class Test2 { A a = get(A.class); // this statement gets error // how should the next method be defined? <T, U extends B<? super T>> U get(Class<U> c) { return null; } } class A<T> extends B<T> {} class B<U> {}
FWIW, the sample in #15 compiles w/ JDK 1.7 and w/ NetBeans 6.5.1.
(In reply to comment #9) > And we do not get to pick and choose which aspects of the spec we follow. But it appears to be possible to pass the TCK with the preious behaviour. I have tested with JROCKIT 1.6, Sun JDK 1.6 and 1.7, and NetBeans 6.5.1, and they all compile the simple sample. Is it really necessary to be this strict when the rest of the industry does not appear to be?
(In reply to comment #9) > You do not have to reopen the bug to add a comment. But nobody seems to follow up on posts after this has been closed. > Because its a raw type. If you replace the raw type reference, you will not see > this problem. Would someone who understands what this means please explain how to resolve the issue using the simple example that was posted in #4? Thanks.
Michael - please read comment #6 From our understanding of the spec, you cannot write : A a = get(A.class); <T, U extends B<? super T>> U get(Class<U> c) { return null; } and expect A as the answer. I accept this is frustrating/annoying for people who have existing code which uses this pattern, but we cannot ignore the spec.
(In reply to comment #19) Kent, Thanks for the quick response. > From our understanding of the spec, you cannot write : I am in no position to challenge anyone on the spec. I assume that your reading is correct, and that the change for 3.5 is indeed a correction. That said, I cannot find another compiler that raises this as an error. The Eclipse 3.5 compiler is the only one that will not compile our code. Sun's own JDKs (including the current 1.7 builds) compile this code without error. It really seems strange to me that no other vendor has taken the position that Eclipse has on this item in the spec. Has anyone at Eclipse contacted Sun on this? Perhaps raised it as a bug with the Sun implementation to see how they respond. Is it possible that the spec is incorrect? How is it possible for other JDKs to pass the TCK? Michael
*** Bug 281993 has been marked as a duplicate of this bug. ***
To provide some more info - the original change to MesssageSend.resolveType() was from bug 258798
*** Bug 283306 has been marked as a duplicate of this bug. ***
*** Bug 283575 has been marked as a duplicate of this bug. ***
(In reply to comment #4) The current JDK 1.7 only gives a warning: $ java -version java version "1.7.0-ea" Java(TM) SE Runtime Environment (build 1.7.0-ea-b65) Java HotSpot(TM) Client VM (build 16.0-b06, mixed mode, sharing) $ java -Xlint:unchecked Test.java Test.java:2: warning: [unchecked] unchecked method invocation: method get in class Test is applied to given types A a = get(A.class); ^ required: Class<U> found: Class<A> where U,T are type-variables: U extends B<? super T> declared in method <T,U>get(Class<U>) T extends Object declared in method <T,U>get(Class<U>) 1 warning > Simpler case : > class Test { > A a = get(A.class); > <T, U extends B<? super T>> U get(Class<U> c) { return null; } > } > class A<T> extends B<T> {} > class B<U> {} > javac issues an unchecked method invocation: method get in class Test is > applied to given types > required: java.lang.Class<U> > found: java.lang.Class<A> > In 3.4.x we do not report an error or an unchecked method invocation. > In 3.5RC2, we report both an unchecked method invocation & type mismatch error: > cannot convert from B to A
Anything new on this, or should we consider switching to another ide ie. netbeans, that can compile the code via suns jdk. I still feel that eclispe should bent the implementation to follow the de facto standard, it's not just one jdk that can compile the code it's all but eclipse..
(In reply to comment #26) > I still feel that eclispe should bent the implementation to follow the de facto > standard, it's not just one jdk that can compile the code it's all but > eclipse.. As far as I know, there are two Java compilers: javac and the Eclipse compiler. If you know another one, please let me know. We will contact Sun to sort this out. Meanwhile I keep this bug closed as it is not sure that anything will change. If it ends up being an problem with our compiler, you can be sure we will reopen and fix accordingly.
*** Bug 294724 has been marked as a duplicate of this bug. ***
Please see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6791481 where it is acknowledged that sun's implementation diverges from JLS 15.12.2.6. In particular this program compiles with unchecked conversion warning but with no errors on javac 5,6,7 : class Test<X> { X m(Class<X> c) {return null;} X x = m((Class)String.class); } Note: Eclipse HEAD also compiles the programs without the unchecked warning, but that is a bug: I have raised bug# 294944. Stay tuned as this gets investigated further.
(In reply to comment #29) > Please see > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6791481 > where it is acknowledged that sun's implementation > diverges from JLS 15.12.2.6. The particular manner in which javac is documented to diverge is somewhat different though: "Only generic methods are considered when checking as to whether return/thrown types should be erased or not following an unchecked conversion" The current issue is at hand is around the phrase "erasure of the method's declared return type" in the sentence: ^^^^^^^^ "Otherwise, if unchecked conversion was necessary for the method to be applicable then the result type is the erasure (§4.6) of the method’s declared return type." > In particular this program compiles with unchecked conversion > warning but with no errors on javac 5,6,7 : > class Test<X> { > X m(Class<X> c) {return null;} > X x = m((Class)String.class); > } > Note: Eclipse HEAD also compiles the programs without the unchecked > warning, but that is a bug: I have raised bug# 294944. > Stay tuned as this gets investigated further. Actually, the unchecked warning does come with eclipse, but the needed erasure per 15.12.2.6 doesn't kick in resulting in this program being compiled without error (as would be required per JLS). I'll leave this behavior as it is for now until further investigation throws more light.
(In reply to comment #30) > (In reply to comment #29) > > Please see > > http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6791481 > > where it is acknowledged that sun's implementation > > diverges from JLS 15.12.2.6. > The particular manner in which javac is documented to diverge > is somewhat different though: We have acknowledgement from Sun that javac's implementation pertaining to JLS 15.12.2.6 is incorrect and deviates from JLS 15.12.2.6. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6791481 while not identical is similar enough that the current issue would fall under the same sun bug. The last words on http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6791481 reads: "TODO: investigate the compatibility risk of this change as it could cause compilation errors on programs that used to be accepted. Posted Date : 2009-01-08 13:49:01.0" Olivier, what do you suggest ? Philippe, a couple of questions: 1. Do you remember what was the driver behind bug# 258798 ? Was this internally raised ? 2. Quoted from bug# 258798 comment#0 : class Foo<T> {} public class X { public void test() { Integer i = m(new Foo<Foo<Integer>>(), new Foo()); } public <T> T m(Foo<T> x, T t) { return t; } } should surface an error where the return type got erased: Type mismatch: cannot convert from Foo to Integer instead of: Type mismatch: cannot convert from Foo<Integer> to Integer --- Did you mean to say : Type mismatch: cannot convert from Object to Integer ? -- Thanks.
The generic inference was not complying to JLS 15.12.2.6 prior to this fix. It would simply answer a raw method substitution, losing the fact certain elements could be better inferred than raw types. We had several symptoms of this, which got taken care by bug 258798, and it should not be reverted for that matter. Now, it could be tuned a bit if not reconciliable with javac. For instance, we currently answer a raw form of the type original variable erasure, as opposed to simply erasing the inferred return type (a la javac). While this is acknowledged as a bug, until Sun fixes it, I understand this being problematic. My vote would be to ask them whether they will act on it or not given the "TODO: investigate...", and align accordingly. > --- Did you mean to say : > Type mismatch: cannot convert from Object to Integer ? Well, at the time I wrote that, I probably had not yet realized that we were supposed to erase original variable, but was only erasing the inferred return type. NOTE: from conversations back then, I remember that such semantics were also to apply to non generic method invocations as well (which we are not doing, but JLS 15.12.2.6 is not only for generic invocations). The reasoning being that raw types were not to be forgiving...
javac team is "not actively investigating this issue anymore". In looking at the test case attached to this defect as well as the myriad duplicates, it appears that inserting a simple cast should make the programs compile alright in all the cases retaining the same meaning as they had/have under javac and eclipse 3.4. After all, the erasure of the declared return type vs the inferred return type which javac is admittedly erroneously using does not change the dynamic type of the object -- only the compile time notion. Granted, this is ugly, inelegant and cumbersome, but will unblock us. Is something being overlooked or oversimplified here ?
> it appears that inserting a simple cast ... Can you give an example of what you have in mind ? I was thinking of changing the way we erase in that scenario.
(In reply to comment #34) > > it appears that inserting a simple cast ... > Can you give an example of what you have in mind ? > I was thinking of changing the way we erase in that scenario. What I had in mind was given: class Test { A a = get(A.class); // fails to compile with 3.5 as get is seen // to return a B and not A as was with 3.4 <T, U extends B<? super T>> U get(Class<U> c) { return null; } } class A<T> extends B<T> {} class B<U> {} if the offending line was changed to A a = (A) get(A.class); the program should be semantically identical to the code generated by 3.4 and javac. But that is simplistic - the altered return type could have ripple effects and influence other things as the program below shows: so my suggestion that a simple cast should fix the problem is not valid. class Test { A a = (A) get(A.class); int f = m(get(A.class)); <T, U extends B<? super T>> U get(Class<U> c) { return null; } public int m(A a) { return 0; } public int m(B b) { return 1; } public static void main(String [] args) { Test t = new Test(); System.out.println(t.f); // prints 0 with 3.4 and 1 with 3.5 } } class A<T> extends B<T> {} class B<U> {}
The change I have in mind is the following: in MessageSend#resolveType(...) locate the following lines near the bottom: [...] TypeBinding returnType; if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) { >> returnType = this.binding.original().returnType; if (returnType != null) { returnType = scope.environment().convertToRawType(returnType.erasure(), true); } } else { [...] and replace: >> returnType = this.binding.original().returnType; with: >> returnType = this.binding.returnType; Sorry I need to recreate a dev environment to create a patch...
(In reply to comment #36) > The change I have in mind is the following: > in MessageSend#resolveType(...) locate the following lines near the bottom: > [...] > TypeBinding returnType; > if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) > { > >> returnType = this.binding.original().returnType; > if (returnType != null) { > returnType = scope.environment().convertToRawType(returnType.erasure(), > true); > } > } else { > [...] > and replace: > >> returnType = this.binding.original().returnType; > with: > >> returnType = this.binding.returnType; > Sorry I need to recreate a dev environment to create a patch... Philippe, Thanks, I had already tested such a version and it works ok. Other than a handful of failures in GenericTypeTests all seem to be ok. These "failures" are along the expected lines due to the changed behavior in the experimental fix and would call for remastering the test case.
You also need to apply a similar change for thrown exceptions: org.eclipse.jdt.internal.compiler.ast - compiler - org.eclipse.jdt.core AllocationExpression#analyseCode(BlockScope, FlowContext, FlowInfo) ExplicitConstructorCall#analyseCode(BlockScope, FlowContext, FlowInfo) MessageSend#analyseCode(BlockScope, FlowContext, FlowInfo) QualifiedAllocationExpression#analyseCode(BlockScope, FlowContext, FlowInfo) and also make the same change in code snippet support: org.eclipse.jdt.internal.eval - eval - org.eclipse.jdt.core CodeSnippetMessageSend#resolveType(BlockScope)
Feels also this should be propagated back to 3.5.x stream given community reactions.
Daniel, once the patch is ready we would like to release a fix for 3.5.2. +1 ?
(In reply to comment #39) +1
I tend to +1 for backporting but I'd like to see a patch before deciding: if it's too big and/or risky then we might not do it.
While working on this, I tripped into another defective behavior and have raised bug# 295964. The related tests are passing as of now, but only fortuitously so.
Created attachment 152933 [details] Proposed patch Proposed patch to align with javac behavior.
Created attachment 152934 [details] New and changed tests Patch for new and changed tests.
Fix and tests released in HEAD for 3.6M4. 3.5.2 patch to be posted shortly.
Created attachment 153032 [details] Source + Tests cumulative patch for 3.5.2 stream. Patch to backport to 3.5.2 stream.
Created attachment 153033 [details] Source only patch for 3.5.2 stream Dani, please take a look at this proposed backport to 3.5.2
Good work! +1 for 3.5.2.
Released in 3.5.2 maintenance stream. Thanks everybody for your patience.
(In reply to comment #50) > Released in 3.5.2 maintenance stream. Thanks everybody for your patience. This is great news. The effort is appreciated. This was the only issue blocking my teams migration to Galileo. I see the release plan for 3.5.2 is 2010-02-26. What is the best option for a stable build prior to 3.5.2?
HI, Great work guys ! But I still have a issue :( The following code gives me an error saying that the get methods have the same erasure. The code below compiles in Suns JDK public class Testing { public <L extends Logic> L get(Class<L> logicClass) { return null; } public <L extends SingletonWrapperLogic<?>> L get(Class<L> logicClass) { return null; } } class AbstractLogic { } class Logic extends AbstractLogic { } class SingletonWrapperLogic<WRAPPED> { }
Soren this bug as initially reported is fixed and backported to 3.5.2. Please open a new bug report for your problem and lets discuss it there.
(In reply to comment #53) > Soren this bug as initially reported is fixed and backported to 3.5.2. Please > open a new bug report for your problem and lets discuss it there. To save everyone some cycles, I believe this latest issue reported is a duplicate of https://bugs.eclipse.org/bugs/show_bug.cgi?id=289247 https://bugs.eclipse.org/bugs/show_bug.cgi?id=273862 See the sun bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950 fixed and released in 7b55 release of javac. So this code will be rejected by more recent versions of javac. When fed to 7b75 I get: C:\jtests>C:\jdk-7-ea-bin-b75-windows-i586-30_oct_2009\jdk7\bin\javac -Xlint:unc hecked -sourcepath c:\jtests Testing.java Testing.java:6: name clash: <L#1>get(Class<L#1>) and <L#2>get(Class<L#2>) have t he same erasure public <L extends SingletonWrapperLogic<?>> L get(Class<L> logicClass) { ^ where L#1,L#2 are type-variables: L#1 extends SingletonWrapperLogic<?> declared in method <L#1>get(Class<L#1>) L#2 extends Logic declared in method <L#2>get(Class<L#2>) 1 error C:\jtests>
(In reply to comment #51) > (In reply to comment #50) > > Released in 3.5.2 maintenance stream. Thanks everybody for your patience. > This is great news. The effort is appreciated. > This was the only issue blocking my teams migration to Galileo. I see the > release plan for 3.5.2 is 2010-02-26. What is the best option for a stable > build prior to 3.5.2? While there will be several periodic builds and release candidates builds in the 3.5.2 branch leading upto 3.5.2 release that you can use to test, 3.5.2 is the next full release.
Verified for 3.6M4 using build I20091207-1800
*** Bug 299104 has been marked as a duplicate of this bug. ***
*** Bug 299367 has been marked as a duplicate of this bug. ***
Verified for 3.5.2 RC2 using build M20100120-0800
Verified.
*** Bug 268798 has been marked as a duplicate of this bug. ***
Originally discussed here http://stackoverflow.com/questions/26186767/generics-function-call-not-compiling-in-java-8-extending-multiple-interfaces
(In reply to Jigar Joshi from comment #62) > Originally discussed here > > http://stackoverflow.com/questions/26186767/generics-function-call-not- > compiling-in-java-8-extending-multiple-interfaces Couldn't be. Unless you guys at Stackoverflow are time travellers. I think you meant to add this comment at https://bugs.eclipse.org/bugs/show_bug.cgi?id=446223
Sorry, commented in wrong thread