Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 345065 - [1.5][compiler] intersection types including class type element fail on covariant return
Summary: [1.5][compiler] intersection types including class type element fail on covar...
Status: CLOSED WONTFIX
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: All All
: P3 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-07 18:51 EDT by Ben Schulz CLA
Modified: 2020-05-02 08:32 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ben Schulz CLA 2011-05-07 18:51:41 EDT
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
Comment 1 Stephan Herrmann CLA 2011-05-08 03:11:08 EDT
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().
Comment 2 Ben Schulz CLA 2011-05-08 09:54:52 EDT
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.
Comment 3 Ben Schulz CLA 2011-05-08 10:38:22 EDT
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.
Comment 4 Ayushman Jain CLA 2011-05-09 01:28:02 EDT
Srikanth, please clarify the expected behaviour here. Javac 7 also compiles this fine. TIA
Comment 5 Eclipse Genie CLA 2020-05-02 08:32:40 EDT
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.