| Summary: | Reference ambiguous for javac, not for JDT | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Mauro Molinari <mauromol> |
| Component: | Core | Assignee: | Sasikanth Bharadwaj <sasikanth.bharadwaj> |
| Status: | CLOSED WONTFIX | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | jarthana, sasikanth.bharadwaj, stephan.herrmann |
| Version: | 4.4.2 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | stalebug | ||
Same difference can also be observed when compiling for 1.8. But, looking at InterfaceB, can you tell my, why 'T' would appear in any signature? InterfaceB does not extend InterfaceA, it extends InterfaceA<String> which doesn't have a method foo(T), only a method foo(String). At first glance this looks like javac is failing to do a necessary type parameter substitution. Am I missing anything? Could the above be expanded to create ambiguity between non-abstract methods? I could imagine that javac's error message is borken, it may be trying to tell us something different (e.g., regarding erased signatures not being override compatible or such), but any reasonable error in this category should IMHO be reported against the definition of InterfaceB, not against its clients. There's a question/answer on StackOverflow that might be explaining why this happens: I said "might" because I admit I've not read it so carefully enough to determine it's the exact same problem, although the question seems to suggest this. Here it is: http://stackoverflow.com/questions/8966397/why-does-implementing-this-generic-interface-create-an-ambiguous-reference Another hint: if InterfaceC is itself InterfaceC<T> and then InterfaceB implements both InterfaceA<String> and InterfaceB<String>, then no ambiguous reference error is given any more by javac. The error is back if T has different bounds in InterfaceA and InterfaceC: if we use, say, JTree (any non-final class) instead of String and you have: InterfaceA<T> InterfaceC<T extends JTree> InterfaceB extends InterfaceA<JTree>, InterfaceC<JTree> javac complains again. (In reply to Mauro Molinari from comment #2) > There's a question/answer on StackOverflow that might be explaining why this > happens: I said "might" because I admit I've not read it so carefully enough > to determine it's the exact same problem, although the question seems to > suggest this. > Here it is: > http://stackoverflow.com/questions/8966397/why-does-implementing-this- > generic-interface-create-an-ambiguous-reference Thanks, this may save us a lot of time weighing the letters of JLS against each other. The part that I was fearfully suspecting is this: "... and the signatures of all of the maximally specific methods have the same erasure ..." In a parameterized world, Java can see that both methods are equivalent, but at the bare metal we have to give an erased signature for the "invoke" bytecode instruction, and here we cannot decide between foo(Ljava.lang.String;)V and foo(Ljava.lang.Object;)V. Gee whizz, so it is explicitly legal to create a type which you cannot use. We need to look for the missing comparison of erasures in Scope.mSMB(). Always missing? Missing only on some path? Consider 1.7- and 1.8+ modes ... Anyone? Sasi, can you take this forward? Thanks! 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. I can still see no complain from JDT with 1.8 compliance in Eclipse 2018-12, but complain from javac 1.8.0.202. I don't have the ability to test with newer javac versions right now though. |
Consider the following interfaces: public interface InterfaceA<T> { void foo(T foo); } public interface InterfaceC { void foo(String foo); } public interface InterfaceB extends InterfaceA<String>, InterfaceC { } And the client class: public class Test { public static InterfaceB factory() { return null; // irrelevant here } public Test() { InterfaceB ib = Test.factory(); ib.foo("foo"); } } Compiling with JDT is fine (using Java7 compliance). Compiling with javac produces the following: test\Test.java:12: error: reference to foo is ambiguous, both method foo(String) in InterfaceC and method foo(T) in InterfaceA match ib.foo("foo"); ^ where T is a type-variable: T extends Object declared in interface InterfaceA 1 error