PROPOSAL: language support for JSR 292

John Rose John.Rose at Sun.COM
Fri May 1 13:35:09 PDT 2009

On Apr 30, 2009, at 2:55 AM, Maurizio Cimadamore wrote:

> 1) I'd strongly recommend to forbid usage of InvokeDynamic type in the
> following contexts:
> (i) extends clause (e.g. class MyDynamic extends InvokeDynamic)
> (ii) type-parameter bound (e.g. class Foo<X extends InvokeDynamic &
> Comparable<?>>)
> (iii) wildcard type-argument (e.g. Foo<? extends InvokeDynamic)

I agree, but let's do that regularly for java.util.Collections,  
java.lang.String, and every other type which can be statically proven  
not to have supertypes.

I'll make InvokeDynamic final also, for good measure.

> 2) I agree with Neal that the usage of Void feels a bit hacky. If you
> need null values to be typed differently then I agree that probably
> adding java.lang.Null would be the best thing to do, rather than
> overriding the semantics of Void.

Yes, it's hacky.  I'd be happy to fold null support into the proposal  
(though not this month).

Since there seems to be support for adding java.lang.Null, I'll  
retract the Void feature from the spec:

1.4 For the purposes of determining the descriptor of the  
invokedynamic instruction, null arguments (unless casted to some other  
type) are deemed to be of reference type java.lang.Null, if this type  
exists. The type Null will appear only to the bootstrap method, and  
will serve notice that the call site contains an untyped null  
reference, rather than an explicitly typed reference.

   InvokeDynamic.myPrintLine(null);  // type (Null) -> Object
   InvokeDynamic.<void>foo((String)null, null);  // type (String,  
Null) -> void

> 3) InvokeDynamic and type-inference. It seems like you can optionally
> provide a type-parameter denoting the dynamic call's expected return
> type. This is fine, as long as it is consistent with JLS and

Thanks for the citations.  There's no interaction with these sections  
because there is no test for applicability, and none of the implicit  
methods of InvokeDynamic have type parameters.  Both 1.2 and 2.2  
should say more clearly that the type of an implicit method is derived  
from the erasure of the arguments, and 1.3/2.3 should say that the  
return type of the method is derived from the erasure of the declared  
return type (or Object by default).  If you use generic types around a  
dynamic call site, you'll get lots of unchecked warnings, and this is  
a feature not a bug.

> In your examples it seems like the usage of such type
> argument is completely optional. If specified, it provides additional
> info about the dynamic call site such that, e.g. the following code  
> will
> be rejected:
> int i = InvokeDynamic.<String>myDynMethod("Hello!"); // type  
> (String) ->
> String
> Can this optional type argument be inferred so that the following  
> method
> call will behave identically?

I'd rather have the return type of a dynamic call site be clearly  
marked, or default to a fixed type.  (I would prefer Dynamic, but  
since that doesn't exist now, Object will do fine.)  That provides a  
clearer demarcation between the statically typed surrounding code and  
the dynamic call site.

> int i = InvokeDynamic.myDynMethod("Hello!"); // type (String) ->  
> String
(Comment should be type (String) -> Object, of course.)
> [I did some testing and it seems like inference is not supported - the
> above line will give an incompatible types error, found Object,  
> expecetd
> int]

Yes.  Such things will work automagically for receiver calls to  
dynamic, but not in the present proposal:

Dynamic d = ...;
int i = d.myDynMethod("Hello!"); // type (Dynamic, String) -> Dynamic  
~> int

> If so, you are mimicking an under-constrained type-variable (a method
> type variable that cannot be inferred from actual arguments passed to
> the method). This raises a question: what happens when the dynamic  
> call
> site does not appear within an assignment context, e.g.
> InvokeDynamic.myDynMethod("Hello!");
> or
> int i = (Integer)InvokeDynamic.myDynMethod("Hello!");

1.3 and 2.3 state that the default return type is Object, which serves  
in that role as a universal dynamic type.

> An alternative would be to pass to InvokeDynamic the return type Class
> object corresponding the to expected return type as the first  
> parameter
> of the dynamic call:
> InvokeDynamic.myDynMethod(int.class, "Hello!"); // type (String) ->  
> int
> This has the advantage of not requiring a separate language  
> extension in
> order to allow primitive type (and void) to be specified as  
> parameter types.

The type of int.class is not Class<int> but Class<Integer>, which  
means it doesn't really say what it appears to say.  Plus, having an  
extra leading argument, but not passing it as a real argument, would  
be a highly confusing variation on the normal meaning of method  
argument lists.

As I said to Howard Lovatt, I think a faux type parameter, while not  
perfect, is the best of the known choices.

-- John

More information about the coin-dev mailing list