[jsr-292-eg] Conversion of method reference to MethodHandle

John Rose john.r.rose at oracle.com
Tue May 14 17:19:28 PDT 2013


[Catching up on some 292 EG stuff...]

On Dec 31, 2012, at 4:16 AM, Jochen Theodorou <blackdrag at GMX.ORG> wrote:

> I think not allowing overloaded methods will restrict the usage quite a lot.

For me, the restriction against overloaded methods is a killer.  I'm sad but philosophical about this.

As I told Brian, I was hoping the Lambda folks would find themselves required to add overload disambiguation to member references, along the lines Jochen suggested — 'PrintStream::println(int)' – at which point we 292'ers could ask for MethodHandle (and jlr.Method) as target types.

I still think it may be worth doing, but only if the syntax is competent beyond the 99% level to describe all methods and constructors (which the overloading restriction prevents).  Fields would be good too, but those seem to be even farther off the table.

For the record, there might be a couple of other approaches.  I am not proposing these seriously for JDK 8, but here they are, A and B.

A. Define enough extra poly-to-interface conversions to allow a universal functional type to be defined. [1]

  UniversalFunction uf0 = ()->8;
  UniversalFunction uf1 = String::concat;
  UniversalFunction uf2 = (int n)->{System.out.println(n);}

Then define a cracking API that can conspire with the metafactory for uf0, uf1, and uf2 to crack out the insides.

B. (This is from an idea suggested by Brian.)  Define javac-time constant folding rules for the following methods:
   MethodHandles.lookup()
   MethodType methodType(...)
   Lookup.findVirtual() ...

When an expression involving only these (with constant String and Class leaves) can be proven to resolve at compile time, replace the expression with a CONSTANT_MethodHandle or CONSTANT_MethodType.

Maybe gate the whole thing on an annotation @MustBeAConstantPoolConstant, to avoid surprises after compile time.

Would require either harmonizing the CONSTANT_MethodHandle resolution rules with the Lookup.findFoo rules, or special dispensation to vary the exception types from ReflectiveOperationException to LinkageError.

Anyway, this note is to put some ideas out for longer-term thought.

My next message will discuss the proposal for the MethodHandleInfo API, for cracking "direct" method handles only.

— John

[1] A universal functional type could look something like this:

  @FunctionalInterface interface MyUniversal<R,X> {
    R myApply(@CastThisCovariantPolyArgument Object... anyArgs) throws X;
  }

So:

  MyUniversal<?,?> foo = (int n, String s)->{System.out.println(n+": "+s);}

evaluates to something like:

  MyUniversal<?,?> foo = new MyUniversal<Void,RuntimeException>() {
    @Override Void myApply(Object[] av) {
      if (av.length != 2)  throw new WrongMethodTypeException();
      int n = (int)av[0]; String s = (String)av[1];
      {System.out.println(n+": "+s);}
    }
  }

I'm not sure if this idea is good for much besides a target type that always wins.
Any random call like 'foo.myApply(1, 2, false)' would likely throw a WMTE or CCE.
Then there is the question of how these covariant varargs guys interact with the "most specific overloading" rules.
(Method handles make signature polymorphism work by exposing their type and allowing asType conversions.)



More information about the lambda-spec-observers mailing list