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

javac is not correctly filtering non-members methods to obtain the function descriptor

XMLWordPrintable

    • b134
    • x86
    • os_x
    • Verified

      FULL PRODUCT VERSION :
      java version "1.8.0_05"
      Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Mac OS X 10.9.3

      A DESCRIPTION OF THE PROBLEM :
      Consider this snippet of java 8 code:

      public class Generics {
        public static <V, E extends Exception> V f(CheckedCallable1<V, E> callable) throws E {
          return callable.call();
        }
        public static <V, E extends Exception> V g(CheckedCallable2<V, E> callable) throws E {
          return callable.call();
        }
        public static void main(String[] args) throws Exception {
          f(() -> 1);
          g(() -> 1);
        }
      }

      interface Callable<V> {
        V call() throws Exception;
      }

      interface CheckedCallable1<V, E extends Exception> {
        V call() throws E;
      }

      interface CheckedCallable2<V, E extends Exception> extends Callable<V> {
        @Override V call() throws E;
      }

      The lambda at the call to f compiles fine, whereas the lambda at the call to g does not compile, but rather gives this compile error:

      Error:(10, 7) java: call() in <anonymous Generics$> cannot implement call() in CheckedCallable2
        overridden method does not throw java.lang.Exception

      I believe this is a compiler bug, in particular since the identical code with Exception replaced with IOException compiles fine.

      Additional details are at http://stackoverflow.com/questions/24199148/lambdas-and-functional-interfaces-with-generic-throw-clauses

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile the following java code:

      public class Generics {
        public static <V, E extends Exception> V f(CheckedCallable1<V, E> callable) throws E {
          return callable.call();
        }
        public static <V, E extends Exception> V g(CheckedCallable2<V, E> callable) throws E {
          return callable.call();
        }
        public static void main(String[] args) throws Exception {
          f(() -> 1);
          g(() -> 1);
        }
      }

      interface Callable<V> {
        V call() throws Exception;
      }

      interface CheckedCallable1<V, E extends Exception> {
        V call() throws E;
      }

      interface CheckedCallable2<V, E extends Exception> extends Callable<V> {
        @Override V call() throws E;
      }

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expect this code to compile.
      ACTUAL -
      The call to g results in the following compile error:

      Error:(10, 7) java: call() in <anonymous Generics$> cannot implement call() in CheckedCallable2
        overridden method does not throw java.lang.Exception

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Error:(10, 7) java: call() in <anonymous Generics$> cannot implement call() in CheckedCallable2
        overridden method does not throw java.lang.Exception

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class Generics {
        public static <V, E extends Exception> V f(CheckedCallable1<V, E> callable) throws E {
          return callable.call();
        }
        public static <V, E extends Exception> V g(CheckedCallable2<V, E> callable) throws E {
          return callable.call();
        }
        public static void main(String[] args) throws Exception {
          f(() -> 1);
          g(() -> 1);
        }
      }

      interface Callable<V> {
        V call() throws Exception;
      }

      interface CheckedCallable1<V, E extends Exception> {
        V call() throws E;
      }

      interface CheckedCallable2<V, E extends Exception> extends Callable<V> {
        @Override V call() throws E;
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      1) Don't extend a functional interface without a generic throws clause in a functional interface with a generic throws clause.

      or

      2) Use a subclass of Exception on the functional interface without generic throws clause.

            vromero Vicente Arturo Romero Zaldivar
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: