Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8199123

AssertionError when compiling reference to abstract class' method, defined in interface, when other non-abstract same-named method exists

XMLWordPrintable

    • x86_64
    • linux

      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));

        1. Bug.java
          0.3 kB
          Fairoz Matte

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: