Summary: | [1.5][compiler] Incompatible type bounds message points to the generic type instead of its type parameter | ||||||
---|---|---|---|---|---|---|---|
Product: | [Eclipse Project] JDT | Reporter: | Greg Gibeling <gdgib> | ||||
Component: | Core | Assignee: | Maxime Daniel <maxime_daniel> | ||||
Status: | VERIFIED FIXED | QA Contact: | |||||
Severity: | normal | ||||||
Priority: | P3 | CC: | philippe_mulet | ||||
Version: | 3.3 | ||||||
Target Milestone: | 3.3 M5 | ||||||
Hardware: | PC | ||||||
OS: | Windows XP | ||||||
Whiteboard: | |||||||
Attachments: |
|
Description
Greg Gibeling
2006-11-06 15:34:43 EST
Using HEAD, we return: ---------- 1. ERROR in D:\tests_sources\test\A.java (at line 1) public class A<X extends B & C> {} ^ The return type is incompatible with C.method(), B.method() ---------- 1 problem (1 error) Javac 1.5.0_09 and 1.6b104 are compiling it without any error. Not a regression from 3.2.0. 3.2.0 reports exactly the same error. From JLS 3 4.9, I would contend that we rightly complain, because no class could implement both B and C - and javac would be wrong in that case (Philippe, do I miss something?). Note that javac complain if we attempt to have a class Y implement both B and C, with or without implementations for method. This would leave us with some need to improve the error message. I believe that the message as described in comment #1 makes plainly clear that the problem has to do with C#method and B#method. Which leaves us with A being underlined instead of X. I will investigate how easy (or difficult) it would be to do so. I somehow remember that there are cases where the complaint is deferred until actually trying to instantiate such an object; where a standard bound mismatch will arise from not being able to satisfy both constraints. So maybe we could be doing too much work eagerly. Something to check: public class A<X extends B & C> { void foo(X x) { x.method(); } } public interface B { public int method(); } public interface C { public boolean method(); } I would assume that if #method() gets invoked some complaint is issued. Side-note, even if complaining on type parameter was too harsh, it would still be a useful notification (warning) to emit, so end users would notice the problem sooner than later. Upon: public class X<T extends I & J> { void foo(T t) { t.method(); t.bar(); if (t.CONSTANT > 0); } } interface I { public int method(); void bar(); } interface J { public boolean method(); static final int CONSTANT = 0; } javac says: X.java:3: reference to method is ambiguous, both method method() in J and method method() in I match t.method(); ^ 1 error Which shows that method is unusable, but bar and CONSTANT can be used. This would support the view that we should defer the diagnostic. However, I can still not convince myself that JLS 3 4.9 authorizes that situation, because I cannot build a suitable intersection type. Would you see this as a bug in the spec, or do I miss something about intersection types building or their relationship to variables bounds? http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5061359 says that this is a javac bug, fixed in 1.7 b03. Checked with 1.7 b05 and it complains as we do (except that we misplace the caret). So I will attempt to fix the caret position, and consider that we are right in raising an error. Three things: 1) I cannot imagine any way the java spec could fail to make the declaration "X<T extends I & J>" in comment #6 invalid, as java does not use return types as part of the dynamic signature of a method. Without reading the JLS, just from a language theory standpoint, the combination of I&J must be invalid, and so should be reported, presumeably ASAP. As further evidence I have no idea how such a combination could ever be represented in the java reflection API, nor how dispatch could be handled. Clearly it is impossible to staticly declare a class which matches T, such a class would result in a compiler error. That leaves proxies and direct bytecode generation as the only ways to get such a class, both of which, to my knowledge, have the same expressive power as static declaration. This means that there can never be an instance of T. As the person coding X, wouldn't you want to know that early if possible? 2) I would like to make sure while people are looking at this that there is a passing test which ensures the following code compiles without error: public class A<X extends B & C> {} public interface B { public int method(); } public interface C { public int method(); } 3) Thanks a lot for working on this. It's was a pain is my butt. You're welcome. I'll add your suggested test case close to the others for the sake of completeness if it is not obviously the same as a pre-existing one. Aligning title with conclusions. Created attachment 57585 [details]
Fix + test cases
Fixes the caret position, adds test cases specific for the bug, tunes the pre-existing test cases that were written with a wrong caret position.
Released for 3.3 M5. Verified for 3.3 M5 using warm-up build I20070205-0009 |