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

Add support for captured constants to `LambdaMetafactory` and compilation

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 23
    • tools
    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      Currently, lambdas such as `"<string>"::formatted` or `Foo.class::cast` lead to the returned lambda factory being a constructor,
      whereas lambda expressions like `(...) -> "<string>".formatted(...)` or `o -> Foo.class.cast(o)` return the same hidden class instance every time.

      I propose to extend `LambdaMetafactory.altMetafactory(...)` with a new flag `CONSTANTS` signifying captured constants.
      This flag will add `int capturedConstantsCount` and `Object... capturedConstants` to the end of the `altMetafactory` argument list and require that `factoryType` capture no arguments.
      Captured constants are prepended to the invocation aguments of the implementation method in place of captured arguments.

      `FLAG_CONSTANTS` would then be used when compiling method reference lambdas where the LHS is a constant.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached Java program.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      true
      true
      true
      true
      ACTUAL -
      false
      true
      false
      true

      ---------- BEGIN SOURCE ----------

      import java.util.function.Function;

      public final class LambdaConstantCaptures {
      public static final void main(final String... args) {
      System.out.println(fn1_Ref() == fn1_Ref() ); // prints `false`, would expect `true`
      System.out.println(fn1_Inline() == fn1_Inline() ); // prints `true`

      System.out.println(fn2_Ref() == fn2_Ref() ); // prints `false`, would expect `true`
      System.out.println(fn2_Inline() == fn2_Inline() ); // prints `true`
      }

      private static final Function<String, String> fn1_Ref() {
      return "Hello %s!"::formatted;
      }
      private static final Function<String, String> fn1_Inline() {
      return arg -> "Hello %s!".formatted(arg);
      }

      private static final Function<Object, Foo> fn2_Ref() {
      return Foo.class::cast;
      }
      private static final Function<Object, Foo> fn2_Inline() {
      return obj -> Foo.class.cast(obj);
      }
      }

      public final class Foo {
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Storing the lambda with captured constants in a `static final` field.

      FREQUENCY : always


            dlsmith Dan Smith
            webbuggrp Webbug Group
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: