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

Missing capture conversion for method reference return type

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • None
    • tools
    • None
    • 8

      Consider the following code Java code:

      import java.util.function.Supplier;

      interface Main {
          interface X<T> {
              X<T> self();
          }

          static X<?> makeX() {return null;}

          static <R> X<R> create(Supplier<? extends R> supplier) {return null;}
       
          static X<X<?>> methodRef() {
              return create(Main::makeX).self();
          }

          static X<X<?>> lambda() {
              return create(() -> makeX()).self();
          }
      }

      The method `methodRef` can be compiled without problems, while the method `lambda` is rejected with the following error message:

      Main.java:17: error: incompatible types: X<X<CAP#1>> cannot be converted to X<X<?>>
              return create(() -> makeX()).self();
                                               ^
        where CAP#1 is a fresh type-variable:
          CAP#1 extends Object from capture of ?
      1 error
      error: compilation failed

      According to the specification, the call in methodRef() method should be similarly rejected, as the capture conversion should be applied to the return type (JLS 15.13.2):

      A method reference expression is congruent with a function type if both of the following are true:
      - The function type identifies a single compile-time declaration corresponding to the reference.
      - One of the following is true:
        - The result of the function type is void.
        - The result of the function type is R, and the result of **applying capture conversion** (§5.1.10) to the return type of the invocation type (§15.12.2.6) of the chosen compile-time declaration is R' (where R is the target type that may be used to infer R'), and neither R nor R' is void, and R' is compatible with R in an assignment context.

      Currently, it looks like the type of create(Main::makeX) is X<X<?>>, while it should be X<X<CAP#1>>. The type of create(() -> makeX()) is X<X<CAP#1>>, which is correct.

            Unassigned Unassigned
            tvaleev Tagir Valeev
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: