FULL PRODUCT VERSION :
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux 4.15.5-1-MANJARO #1 SMP PREEMPT Fri Feb 23 18:22:09 CET 2018 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
The Java 1.8 compiler throws an exception when compiling a method reference, probably (according to my experiments) under the following conditions:
- The method reference has a bound receiver, whose type is a generic type parameter that is bounded to an abstract class.
- The method is only defined in an interface of the abstract class.
- The abstract class has another, non-abstract method with the same name as the referenced method (but different signature).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Assuming that the file 'Bug.java' contains the provided source code, and 'javac' refers to a Java 1.8 compiler (e.g. jdk1.8.0_162):
javac Bug.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The classes can be compiled with a Java 1.8 compiler.
(It actually works with a Java 9 compiler.)
ACTUAL -
The compilation fails with an exception and exit code 4.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
An exception has occurred in the compiler (1.8.0_162). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.AssertionError: isSubClass P
at com.sun.tools.javac.code.Symbol.isSubClass(Symbol.java:447)
at com.sun.tools.javac.code.Symbol.isMemberOf(Symbol.java:456)
at com.sun.tools.javac.code.Symbol$MethodSymbol.overrides(Symbol.java:1479)
at com.sun.tools.javac.code.Types$ImplementationCache.implementationInternal(Types.java:2693)
at com.sun.tools.javac.code.Types$ImplementationCache.get(Types.java:2675)
at com.sun.tools.javac.code.Types.implementation(Types.java:2704)
at com.sun.tools.javac.code.Symbol$MethodSymbol.implementation(Symbol.java:1539)
at com.sun.tools.javac.code.Symbol$MethodSymbol.implementation(Symbol.java:1528)
at com.sun.tools.javac.comp.Resolve.notOverriddenIn(Resolve.java:419)
at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:405)
at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:365)
at com.sun.tools.javac.comp.Resolve.selectBest(Resolve.java:1463)
at com.sun.tools.javac.comp.Resolve.findMethodInScope(Resolve.java:1633)
at com.sun.tools.javac.comp.Resolve.findMethod(Resolve.java:1725)
at com.sun.tools.javac.comp.Resolve.findMethod(Resolve.java:1677)
at com.sun.tools.javac.comp.Resolve$MethodReferenceLookupHelper.lookup(Resolve.java:3192)
at com.sun.tools.javac.comp.Resolve.lookupMethod(Resolve.java:3348)
at com.sun.tools.javac.comp.Resolve.lookupMethod(Resolve.java:3333)
at com.sun.tools.javac.comp.Resolve.getMemberReference(Resolve.java:2741)
at com.sun.tools.javac.comp.DeferredAttr$DeferredChecker.visitReference(DeferredAttr.java:1183)
at com.sun.tools.javac.tree.JCTree$JCMemberReference.accept(JCTree.java:1973)
at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
at com.sun.tools.javac.comp.DeferredAttr$FilterScanner.scan(DeferredAttr.java:913)
at com.sun.tools.javac.comp.DeferredAttr.isDeferred(DeferredAttr.java:1100)
at com.sun.tools.javac.comp.Attr.attribArgs(Attr.java:670)
at com.sun.tools.javac.comp.Attr.visitApply(Attr.java:1816)
at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1465)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:576)
at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:625)
at com.sun.tools.javac.comp.Attr.visitExec(Attr.java:1593)
at com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1296)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:576)
at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:645)
at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:661)
at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:1124)
at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:909)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:576)
at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:645)
at com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:1013)
at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:778)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:576)
at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:645)
at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:4364)
at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4272)
at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4201)
at com.sun.tools.javac.comp.Attr.attrib(Attr.java:4176)
at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1248)
at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:901)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:860)
at com.sun.tools.javac.main.Main.compile(Main.java:523)
at com.sun.tools.javac.main.Main.compile(Main.java:381)
at com.sun.tools.javac.main.Main.compile(Main.java:370)
at com.sun.tools.javac.main.Main.compile(Main.java:361)
at com.sun.tools.javac.Main.compile(Main.java:56)
at com.sun.tools.javac.Main.main(Main.java:42)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
interface Container {
void add(Object child);
}
abstract class Panel implements Container {
void add(String text) {
// this is NOT the implementation of the interface method
}
}
class Bug {
<P extends Panel> void bug(P panel, Iterable<Object> children) {
children.forEach(panel::add);
}
}
/* Instead of abstract class Panel and class Bug, this is actually sufficient:
abstract class MinimalExample implements Container {
<P extends Panel> void add(P panel, Iterable<Object> children) {
children.forEach(panel::add);
}
}
*/
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
If upgrading to Java 9 is not an option, replace the method reference with a lambda:
children.forEach(child -> panel.add(child));