PROPOSAL: language support for JSR 292

Maurizio Cimadamore Maurizio.Cimadamore at Sun.COM
Thu Apr 30 02:55:03 PDT 2009


John Rose wrote:
> On Apr 3, 2009, at 1:25 AM, Joseph D. Darcy wrote:
>
>   
>> Reiterating a point Neal raised, if Dynamic is not related to Object,
>> what does that mean when Dynamic is used as the format type argument  
>> to
>> a type parameter?  What do "? extends Dynamic" and "? super Dynamic"
>> mean to the type system?
>>     
>
> It means something limited like ? extends String or ? super Object.   
> I.e., there aren't any interesting types other than Dynamic itself  
> that match the wildcard.
>
>   
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)

While generics/wildcards are essentially a way to refine static 
type-checking, InvokeDynamic provides a way to disable static checking 
completely. For this reason I don't see the two features going side by 
side in any meaningful way. It is true that now that InvokeDynamic has 
become an abstract holder of static methods, it probably makes less 
sense to write code like the above (apart from (i) which users might be 
tempted to write) - nevertheless the compiler should detect such invalid 
usages and flag them as errors.

My point is that a Java class shouldn't ever need to be parameterized on 
something that is bound by InvokeDynamic (or Dynamic) - as those types 
do not provide the type-system with any info.

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.

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. 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?

int i = InvokeDynamic.myDynMethod("Hello!"); // type (String) -> String

[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]

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!");

In those cases, following 15.12.2.8, the under-constrained type variable 
should be inferred to be its declared bound. What does it mean in this 
case? Object ? Null ? Reading from your examples it seems like if no 
optional type-argument for the return type is provided, no info about 
the return type is included in the MethodHandle type generated by javac. 
Which means that this behavior cannot be explained in terms of generic 
method call/type inference (and thus 15.12.2.7/15.12.2.8).

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.

Maurizio
>> Actually there is a special rule that catching Exception is always  
>> okay
>> per JLS 11.2.3; this program is legal and compiles fine:
>>
>> public class Test {
>>    public static void main(String... args){
>>    try {
>>        ;
>>    } catch (Exception e) {
>>        ;
>>    }
>>    }
>> }
>>
>>     
>
> Thanks.  Amending the example to IOError.
>
>   
>> So what are the notions of identity and equality for method handles?
>>     
>
> Inherited from Object. Nothing special.
>
>   
>> [snip]
>>     
>>> 4.1 As specified above, the interface java.dyn.Dynamic has no
>>> supertypes or members.  As such, it is a bare reference type.  (As an
>>> arbitrary relation, the superclass of Dynamic[] is Object[].)  We
>>>
>>>       
>> Are there any other type building operations besides arrays we need to
>> worry about?
>>     
>
> I don't think so.
>
> List<Dynamic> is impossible for interesting reasons.  The (erased)  
> implementation of List internally makes use of Object.toString,  
> Object.equals, and perhaps other such methods.  These calls are wrong  
> for Dynamic values, since Dynamic (not being a subtype) does not  
> inherit Object.equals and the rest.  This allows a Dynamic object to  
> cleanly model another language, without holes in its method namespace.
>
> (Consider a process-oriented capability for which the name "wait" is  
> significant, or some knowledge representation language that has  
> different notions about "equals".  The MOP doesn't need to special- 
> case those names.  It's a small point but worth defending, I think.)
>
> (In C#, with reified types, they can customize their List<Dynamic> to  
> make a MOP-mediated call to equals, I suppose.)
>
>   
>>> But, the Java operators "==" "!=" "+" "+=" on reference types are
>>> clarified to apply only to reference types which are java.lang.Object
>>> or one of its subtypes; they do not have a predefined meaning if
>>> either operand is dynamic.  The "synchronized" and "throw" statements
>>> cannot be applied to dynamic expressions.
>>>
>>>       
>> So if there is no predefined meaning, are those operations illegal?
>>     
>
> Yes.  More specifically, they are reserved for future use, in case we  
> want to do something with dynamic operator overloading.
>
> (There's a half-baked sketch of what this could mean someday, on the  
> mlvm wiki.  It's not ready to discuss yet.)
>
>   
>>> Facilities which compute type relations (such as
>>> javax.lang.model.util.Types) may need to be updated to take Dynamic
>>> into account.  Generally speaking, the new Dynamic conversions  
>>> operate
>>> in parallel to the implicit boxing conversions.  That is, they add no
>>> new subtype or supertype relations, but they provide a few more ways
>>> for values to be implicitly converted or casted.
>>>
>>>       
>> Yes, I would expect a few changes to the type-related APIs.  They may
>> also need to be changes to programs that assume Object is the root of
>> the reference type hierarchy.  I know I've written annotation  
>> processing
>> code like that and Dynamic would need to be special cased in there.
>>     
>
> Thanks.
>
> As noted in the previous message, I have updated the proposal.
>
> -- John
>
>   




More information about the coin-dev mailing list