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

Compilation error with nested generic functional interface

XMLWordPrintable

    • 9
    • b07
    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      OS
      WIndows10 2004, Debian 10.9
      Java
      9, 10, 11, 16, 17-ea

      A DESCRIPTION OF THE PROBLEM :
      If you nest methods that take a `Function<? Super T, ? Extends T>` as an argument, such as `Optional.map()` or `Stream.map()`, the compiler cannot recognize the type information of the inner method. Refer to the attached source code.

      The conditions are a little more complicated.
      1. Both outer and inner methods must take `java.util.function.Function` as an argument, such as `map()` or `flatMap()`. If you change the outer method to a method that takes a `java.util.function.Consumer`, such as `ifPresent()`, the issue will not occur.
      2. The argument used in a `Function` in the inner `map()` must be the Generic argument of the outer `Function`. If the type of this argument is explicit, this issue will not occur. The important thing is that it must be explicit at the caller, and even if it is explicit at the callee as shown below, compilation will fail.

      // Second argument is String
      private static <T> T returnGeneric(T generic, String s) { return generic; }

      // The error occurs even if you pass the Generic variable to the Second argument
      Optional.of("").map(inner -> returnGeneric("", outer)).ifPresent(String::toString);

      This issue does not occur in Java 8, nor does it occur in Java 9 or later when `-Xdiags:verbose` is added as a javac option. And the issue does not occur while coding in VSCode or IntelliJ.

      REGRESSION : Last worked in version 8u291

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile the attached source code.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Compilation succeeds.
      ACTUAL -
      Compilation fails. The error message is as follows.

      App.java:8: error: incompatible types: invalid method reference
              .ifPresent(String::toString);
                         ^
          method toString in class String cannot be applied to given types
            required: no arguments
            found: Object
            reason: actual and formal argument lists differ in length
      Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
      1 error

      ---------- BEGIN SOURCE ----------
      import java.util.Optional;

      public class App {
        public static void main(String[] args) {
          Optional.of("").map(outer -> {
            Optional.of("")
              .map(inner -> returnGeneric(outer))
              .ifPresent(String::toString);
            return "";
          });
        }

        private static <T> T returnGeneric(T generic) {
          return generic;
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Casting explicitly.

      map(inner -> (String) returnGeneric(outer))
      or
      map(inner -> returnGeneric((String) outer))

      FREQUENCY : always


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

              Created:
              Updated:
              Resolved: