Bug 122881 - [1.5][compiler] Multiple interface inheritance is incompatible with Sun compiler
Summary: [1.5][compiler] Multiple interface inheritance is incompatible with Sun compiler
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 major (vote)
Target Milestone: 3.2 M5   Edit
Assignee: Kent Johnson CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 122617 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-01-06 05:03 EST by Tobias Riemenschneider CLA
Modified: 2006-03-27 03:10 EST (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Riemenschneider CLA 2006-01-06 05:03:22 EST
The following piece of code compiles successfully with Eclipse, whereas Sun's compiler produces the error listed below:

###
public class InterfaceInheritanceTest {

	public static interface I {
		public void test();
	}
	
	public static interface AI extends I {}
	
	public static interface BI extends I {}
	
	public static interface CI extends AI, BI {}
	
	public static interface XI {
		public AI getI();
	}
	
	public static interface YI {
		public BI getI();
	}
	
	public static interface ZI extends XI, YI {
		public CI getI();
	}
}
###
D:\dev\eclipse\workspace\Test>javac InterfaceInheritanceTest.java
InterfaceInheritanceTest.java:24: types InterfaceInheritanceTest.YI and InterfaceInheritanceTest.XI are incompatible; both define getI(), but with unrelated return types
        public static interface ZI extends XI, YI {
                      ^
1 error
###

Sun's compiler version is

###
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)
###
Comment 1 Kent Johnson CLA 2006-01-13 15:17:02 EST
Added MethodVerify test77

Released fix into HEAD
Comment 2 Garret Wilson CLA 2006-01-21 11:34:16 EST
So when this bug is marked as "resolved/fixed", does that mean that the Eclipse compiler will now fail as the Java Sun compiler does? Is that the correct behavior?

I have code for which I switched to the Eclipse compiler because the Sun compiler was failing, for just this reason. I filed the issue with Sun (never receiving a reply) and posted a report on the Java forums (to which no one ever replied), so I don't know which is the correct behavior. But it seems to me the following code should work---and it has funcionality necessary to our application.

public interface ActionControl<C extends ActionControl<C>> extends Control<C>
{
	public ActionModel getModel();
}
 
public interface ValueControl<V, C extends ValueControl<V, C>> extends Control<C>
{
	public ValueModel<V> getModel();
}
 
public interface ActionValueControl<V, C extends ActionValueControl<V, C>> extends ActionControl<C>, ValueControl<V, C>
{
	public ActionValueModel<V> getModel();
}
 
public interface ActionValueModel<V> extends ValueModel<V>, ActionModel
{
}

The 1.5_04 compiler gives me:

"ActionValueControl.java:9: types ValueControl<V,C> and ActionControl<C> are incompatible; both define getModel(), but with unrelated return types
public interface ActionValueControl<V, C extends ActionValueControl><V, C>> extends ActionControl<C>, ValueControl<V, C>"

The getModel() return types may be unrelated in the super interfaces, but the interface being defined clearly returns a type that satisfies both constraints.

Will the resolution of Bug 122881 cause compilation to fail under Eclipse as well? Can you cite some reference indicating that the Java language specifies that this should not compile?
Comment 3 Kent Johnson CLA 2006-01-23 12:16:47 EST
So basically your testcase is:

interface Control {}
interface ValueModel {}
interface ActionModel {}
interface ActionControl extends Control {
	ActionModel getModel();
}
interface ValueControl extends Control {
	ValueModel getModel();
}
interface ActionValueModel extends ValueModel, ActionModel {}
interface ActionValueControl extends ActionControl, ValueControl {
	ActionValueModel getModel();
}

and we are currently producing the same error as javac.

When ActionValueControl is changed to be an abstract class instead of an interface:

abstract class ActionValueControl implements ActionControl, ValueControl {
	public ActionValueModel getModel() {return null;}
}

No error is produced.

I agree with you that this appears to be a javac bug.

I've released another change so we won't complain when its an interface, just as we don't when its an abstract class.
Comment 4 Markus Keller CLA 2006-01-23 13:18:32 EST
*** Bug 122617 has been marked as a duplicate of this bug. ***
Comment 5 David Audel CLA 2006-02-14 08:38:46 EST
Verified for 3.2 M5 using build I20060214-0010
Comment 6 Tobias Riemenschneider CLA 2006-02-28 09:55:28 EST
(In reply to comment #2)
> Can you cite some reference indicating that the Java language specifies
> that this should not compile?

§8.4.8.4 of the Java language specification (second case) says
"If all the inherited methods are abstract, then the class is necessarily an abstract class and is considered to inherit all the abstract methods. A compile-time error occurs if, for any two such inherited methods, one of the methods is not return type substitutable for the other (The throws clauses do not cause errors in this case.)"

This is the case for the shown code fragments. It is a difference wether the methods are inherited or overwritten. Exactly there are two different cases:
>>>> First case
interface Control {}
interface ValueModel {}
interface ActionModel {}
interface ActionControl extends Control {
        ActionModel getModel();
}
interface ValueControl extends Control {
        ValueModel getModel();
}
interface ActionValueModel extends ValueModel, ActionModel {}
interface ActionValueControl extends ActionControl, ValueControl {
        ActionValueModel getModel();
}
<<<<
The interface ActionValueControl inherits the abstract methods getModel() from ActionControl and ValueControl AND defines a new anstract method getModel(). At least ActionValueControl provides THREE abstract methods getModel() and the methods inherited from ActionControl and ValueControl are not return type substitutable. As claimed by the Java language specification, javac (1.5.0_06 and 1.6.0_beta2-b73) ends with a compile time error, while Eclipse accepts the code. Defining ActionValueControl as an abstract class and getModel() as an abstract method is the same case as shown above. The second case will be the act of overwriting the two inherited methods:
>>>> Second case
interface Control {}
interface ValueModel {}
interface ActionModel {}
interface ActionControl extends Control {
        ActionModel getModel();
}
interface ValueControl extends Control {
        ValueModel getModel();
}
interface ActionValueModel extends ValueModel, ActionModel {}
abstract class ActionValueControl implements ActionControl, ValueControl {
        public ActionValueModel getModel() {
                return null;
        }
}
<<<<
Now ActionValueModel inherits two methods getModel() from ActionControl and ValueControl and provides a concrete implementation of the method getModel(). This refers to the first case (second subcase) of §8.4.8.4. I.e., the concrete method implements all inherited abstract methods, because they are return type substitutable and no compile time error occurs using javac as well as Eclipse.
Comment 7 Markus Keller CLA 2006-02-28 10:12:44 EST
Tobias, please read bug 122617 comment 1 (a dup of this bug). §8.4.8.4 does not apply if ActionValueControl is an interface. Rather, see §9.4.1.
Comment 8 Tobias Riemenschneider CLA 2006-02-28 10:21:59 EST
(In reply to comment #7)
> Tobias, please read bug 122617 comment 1 (a dup of this bug). §8.4.8.4 does not
> apply if ActionValueControl is an interface. Rather, see §9.4.1.

OK, didn't noticed the extra section for interfaces.

Comment 9 Tobias Riemenschneider CLA 2006-02-28 10:59:14 EST
(In reply to comment #7)
> Tobias, please read bug 122617 comment 1 (a dup of this bug). §8.4.8.4 does not
> apply if ActionValueControl is an interface. Rather, see §9.4.1.

But the following piece of code is not an interface and should be applied by §8.4.8.4:
>>>>
interface Control {}
interface ValueModel {}
interface ActionModel {}
interface ActionControl extends Control {
        ActionModel getModel();
}
interface ValueControl extends Control {
        ValueModel getModel();
}
interface ActionValueModel extends ValueModel, ActionModel {}
abstract class ActionValueControl implements ActionControl, ValueControl {
        public abstract ActionValueModel getModel();
}
<<<<
Comment 10 Markus Keller CLA 2006-02-28 11:47:05 EST
> But the following piece of code is not an interface and should be applied by
> §8.4.8.4:

Nope, §8.4.8 says that a class only inherits methods that are neither overridden nor hidden. Since ActionValueControl#getModel() overrides the others, there are no inherited methods at all, and so §8.4.8.4 does not come into play.