diamond operator and non-denotable types

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Apr 13 05:49:39 PDT 2010


Paul Benedict wrote:
> Maurizio,
>
> Good response. Would you able to make the compiler's error diagnostic
> verbose enough to emit an error such as:
>
> "Construction with 'new Foo<>()' cannot determine type from
> "Number&Comparator". Please use normal construction syntax."
>   
Hi Paul,
the error message that is currently generated is something like:

TestX.java:4: cannot infer a denotable type argument for Foo<>;
Foo<?> f = new Foo<>() {};
                  ^
  reason: type argument INT#1 inferred for Foo<> is not denotable
  where INT#1 is an intersection type:
    INT#1 extends Number,Comparator<Number>
1 error

The error message is taking advantage of the improved diagnostic support 
--- the intersection type is explicitly described in a 'where' clause 
generated by the compiler, listing all the upper bounds of the type.

Maurizio

> This would help the user, like me, determine the possible types being expected.
>
> Paul
>
> On Mon, Apr 12, 2010 at 3:22 AM, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
>   
>> Paul Benedict wrote:
>>     
>>>> The compiler
>>>> always erases an intersection type to the most appropriate type needed
>>>> in order to preserve the semantics of the program.
>>>>
>>>>         
>>> Maurizio,
>>>
>>> The diamond operator is supposed to be syntactic sugar, right? I don't
>>> think the class file is the problem here; let the compiler collapse
>>> the type as if you were not using the operator.
>>>
>>> Foo<?> f = new Foo<>();
>>>
>>> Just rewrite it like someone would write it in Java 5:
>>> Foo<?> f = new Foo<X>();
>>>
>>>       
>> Hi Paul,
>> if the inference algorithm yields e.g. Foo<Number&Comparator<Number>>, how
>> do you exactly go from this type to a type that the user would write? You'd
>> have to choose between Number and Comparator<Number>, meaning that,
>> depending on your choice, the members of one class or the other will be
>> available for use --- which seems arbitrary, and not consistent with what we
>> do with generic methods. Also consider that it's ot only about intersection
>> types; there are also captured types which might be even harder to
>> 'simplify' (e.g. do you propose to use the upper or lower bound? What if the
>> bound is itself non-denotable?)
>>
>> However, if you decide to keep Foo<Number&Comparator<Number>> as is, you
>> encounter a problem when you try to generate the classfile, in case the
>> diamond operator is of the kind:
>>
>> new Foo<>() {} //anon class
>>
>> in fact, this generates a class of the kind:
>>
>> class Anon$Foo extends Foo<Number&Comparator<Number>> { ... }
>>
>> Which is rather weird --- in fact, there's no way to represent this in the
>> classfile without extending the classfile format and the Signature attribute
>> format, which is way outside the scope of the coin project.
>>
>> Back to your question; is diamond syntactic sugar? On the one hand yes; it
>> provides a way to avoid the need of manually specifying type parameters on
>> class instantiation. However there's a subtle point here: the set of types
>> returned by the inference algorithm is larger than the set of types that can
>> be used in a correct Java programs. What do we do in such cases?
>>
>> In my original email I suggested to reject the program (because it has no
>> equivalent Java counterpart); on the other hand Neal would like to have the
>> program accepted as long as this doesn't interfere with code generation;
>> this means only rejecting the case of anonymous inner class creation.
>>
>> Maurizio
>>
>>     
>>> Paul
>>>
>>>       
>>     




More information about the coin-dev mailing list