| Summary: | [1.5][compiler] intersection types including class type element fail on covariant return | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Ben Schulz <yaxay> |
| Component: | Core | Assignee: | Srikanth Sankaran <srikanth_sankaran> |
| Status: | CLOSED WONTFIX | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | amj87.iitr, stephan.herrmann |
| Version: | 3.7 | ||
| Target Milestone: | --- | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | stalebug | ||
To narrow down the issue let's first assume A was concrete:
class A {
public Number m() { return null; }
}
In this case I believe the compiler is right in rejecting your example based
on JLS 4.9 third bullet. Here the members of the intersection type are
constructed via a hypothetic class:
class Intersect extends A implements B { /* empty body */ }
If you create this class the compiler will correctly complain:
The type Intersect must implement the inherited abstract method B.m() to override A.m()
Only by marking A.m() as abstract we have a chance to create a legal Intersect
(in that case marked as abstract, too - let's assume this is legal).
So my guess is that the checks declaringClass.isInterface() should be
replaced with isAbstract().
Let me see if I understand. You take "a class type (ยง8) with an empty body" to mean "the type defined by a *non-abstract* class declaration with an empty body". I fear that you are right, but it would be a terrible mistake in the spec. It should mean "[...] an *abstract* class declaration [...]". Even if the method was concrete *and final* it could be allowed without issue: There simply would not be a type to substitute for the type parameter (so while it would be useless, it would still be sound). I will say that loosening to isAbstract() will get the jdt to compile my code which is my highest priority. However I really feel the spec is not precise enough here. Okay, I just realized that whether the class is abstract or not is irrelevant as your example demonstrated, but I failed to notice. This is because inheriting a method with a more specific return type from an interface does not automatically reabstract a concrete method inherited from the superclass. This is a real bummer. Srikanth, please clarify the expected behaviour here. Javac 7 also compiles this fine. TIA 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. |
Build Identifier: 20100917-0705 The following code fails to compile. "The return types are incompatible for the inherited methods B.m(), A.m()" is reported as the problem. class X<T extends A & B> {} abstract class A { public abstract Number m(); } interface B { Integer m(); } The source of this bug seems to be located in MethodVerifier15.checkTypeVariableMethods(TypeParameter). The issue only occurs if the class type has a less specific return type than the interface type. Two interfaces with different yet compatible are specifically allowed with the following check: // unrelated interfaces - check to see if return types are compatible if (first.declaringClass.isInterface() && match.declaringClass.isInterface() && areReturnTypesCompatible(match, first)) continue; By my understanding of the JLS testing for interfaces is unnecessary here and leads to this bug, which seems consistent with javac behavior. (Of course both I and javac have been wrong before... ;) Reproducible: Always Steps to Reproduce: 1. have jdt compile the given code