[jdk17u-dev] Withdrawn: 8306854: javac with '-source 7' should honor default methods in implemented Java 8 interfaces
duke
duke at openjdk.org
Tue Jun 20 23:15:10 UTC 2023
On Tue, 25 Apr 2023 14:57:02 GMT, Volker Simonis <simonis at openjdk.org> wrote:
> Reported by Richard Hernandez (riher at amazon.com).
>
> Consider the following example:
>
>
> interface A {
> void foo();
> }
>
>
>
> interface B extends A {
> @Override default void foo() { }
> }
>
>
>
> class C implements B { }
>
>
> If we compile `A.java` and `B.java` with `javac -source 8` and `C.java` with `-source 7` we will get the following error:
>
> $ javac -source 8 A.java
> $ javac -source 8 B.java
> $ javac -source 7 C.java
> C.java:1: error: C is not abstract and does not override abstract method foo() in A
> class C implements B { }
>
>
> I think this is wrong, because `foo()` is implemented as a default method in `B`.
>
> The following, slightly simpler example works perfectly fine, although it also depends on a default method in an implemented interface:
>
>
> interface D {
> default void bar() { }
> }
>
>
>
> class E implements D { }
>
>
>
> $ javac -source 8 D.java
> $ javac -source 7 E.java
>
>
> In the second example, `javac` happily accepts the default implementation of `bar()` from interface `D`.
>
> Interestingly, `ecj` (the [Eclipse Compiler for Java](https://ftp.fau.de/eclipse/eclipse/downloads/drops4/R-4.27-202303020300/ecj-4.27.jar)) compiles both examples without any errors:
>
>
> $ java -jar ecj-4.27.jar -cp . -source 8 A.java
> $ java -jar ecj-4.27.jar -cp . -source 8 B.java
> $ java -jar ecj-4.27.jar -cp . -source 7 C.java
>
>
> I think the problem is in [`com.sun.tools.javac.code.Types::firstUnimplementedAbstractImpl()`](https://github.com/openjdk/jdk17u/blob/22cdf79dce8b2ec7c68e3ba71550d70e4eeb2c48/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java#L3110-L3129), specifically in line 3123:
>
>
> 3123: if (allowDefaultMethods) {
> 3124: MethodSymbol prov = interfaceCandidates(impl.type, absmeth).head;
> 3125: if (prov != null && prov.overrides(absmeth, impl, this, true)) {
> 3126: implmeth = prov;
> 3127: }
> 3128 }
>
>
> Here the check for imlementations of `A::foo()` (`absmeth` in the code snippet above) for class `C` (`impl` in the code snippet above) will only be performed if `allowDefaultMethods` is set to true, but `allowDefaultMethods` is globally set to false by `-source 7`.
>
> Instead of relying on the *global* `-source` setting, I think `firstUnimplementedAbstractImpl()` should rather rely on the class file version of the corresponing class (i.e. `B` in this case) and if that class file version is >= 8, it should consider its default method implementations. I even think that the check for `allowDefaultMethods` could be completely removed, because if the class dep...
This pull request has been closed without being integrated.
-------------
PR: https://git.openjdk.org/jdk17u-dev/pull/1296
More information about the jdk-updates-dev
mailing list