On May 15, 2011, at 9:40 AM, Raffaello Giulietti wrote: > I would expect a WrongMethodTypeException to be thrown by > convertArguments in the following snippet, on the ground that String > is neither a wrapper nor a supertype of a wrapper of int, the return > type of mh0. > > MethodHandle mh0 = lookup.findVirtual(String.class, "length", > MethodType.methodType(int.class)); > MethodHandle mh1 = MethodHandles.convertArguments(mh0, > MethodType.methodType(String.class, String.class)); > > However, build 142 of the JDK 7 (2011-05-12) executes the code without > errors. Is this expected behavior?
This should throw WMT. But, a chained conversion from (String)int to (String)Object to (String)Number must succeed, producing a method handle that is doomed to throw CCE. This should be fixed in build 144. (Note: convertArguments is being removed, since asType does the same job. To factor out the effect of variable-arity method handles on asType, there will be MH.asFixedArity, so that convertArgs(x,y) := x.asFixedArity().asType(y).) The reverse case, of reference to primitive, is a curious question. Suppose we have: MethodHandle mh0 = lookup.findVirtual(Integer.class, "toString", methodType(String.class)) .asType(methodType(String.class, int.class)); // mh0(int x) := ((Integer)x).toString() MethodHandle mh1 = mh0.asType( methodType(String.class, String.class)); Here is another case where there is no hope of this conversion succeeding, and so asType should throw WMT instead of creating mh1. But this one must work, obviously: MethodHandle mh2 = mh0.asType(methodType(String.class, Integer.class)); More interestingly, this also works: MethodHandle mh3 = mh0.asType(methodType(String.class, Object.class)); The semantics of Object->int unboxing is based on java.lang.reflect.Method.invoke. This means that the unboxing can happen from any of the types Byte, Short, Character, or Integer: MethodHandle mh4 = mh0.asType(methodType(String.class, Byte.class)); MethodHandle mh5 = mh0.asType(methodType(String.class, Character.class)); But this one needs to fail with WMT, since there is no way to unbox and widen to get an int: MethodHandle mh6 = mh0.asType(methodType(String.class, Long.class)); Looking back at mh3, we realize that it can fail dynamically in a similar way, if passed a value which is not a boxed byte, char, short, or int: mh3.invoke(42); // OK: int -> Integer -> Object -> Integer -> int mh3.invoke((byte)4); // OK: byte -> Byte -> Object -> Byte -> byte -> int mh3.invoke(0x420000000L); // FAIL: long -> Long -> Object -> Integer CCE mh3.invoke("asdf"); // FAIL: String -> Object -> Integer CCE These rules for asType arise from a mix of concerns: - the normal Java method invocation conversions (JLS 5.3) must be supported, at a minimum - when the target is a reference type, Java casting conversion (JLS 5.5) must be supported also - when the target is a primitive type, the conversions supplied by java.lang.reflect must be supported also The union of these rules preserves some important general symmetries: - Object is always a universal source and destination type - every possible retyping of references is allowed (subject to runtime type checks) - wrapper types can be freely interconverted with their corresponding primitive types - primitives will never be narrowed (truncated, discarding sign or magnitude bits) -- John _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev