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 15.12.2.7 and
> 15.12.2.8.
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
// http://wikis.sun.com/display/mlvm/InterfaceDynamic
> 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