"Model 2" prototype status

Remi Forax forax at univ-mlv.fr
Tue Sep 1 07:36:02 UTC 2015


Did a say that i really dislike the List<any> notation :)

answer (maybe) inlined

On 09/01/2015 04:04 AM, John Altidor wrote:
> Hi Brian,

i'm not Brian, but i will answer nevertheless.

>
>
> I am new to this mailing list. 

welcome :)

>  My PhD dissertation covered subtyping with
> variance and Java wildcards extensively, so the questions you raised in
> this thread are very interesting to me.  I was wondering how you are
> handling the translational aspects of wildcards and specialized generic
> methods.

is your dissertation available ?

>
>
> Your earlier post asked how to represent List<any> in bytecode.  Since
> List<any> is a supertype of both List<int> and List<double>, for example,
> type List<any> should only support operations that can be applied to both
> List<int> and List<double>.  One such operation is counting the number of
> elements using method List.size().  Which byte representation would support
> being able to dispatch List.size() on both an instance of List<int> and an
> instance of List<double> ?

Brian has suggested to create a fake interface containing the common operations with List<int> and List<double> implementing such interface. For me, List<any> should be erased to Object (oh no erasure) and invocation should be done using invokedynamic.

>
>
> It seems such a byte representation would need to be independent of fields.

fields access can be emulated using getters/setters as Brian said.

>
>   The number of bytes needed to represent an instance differs among
> primitive types (e.g. int and double).  As a result, it seems List<int> and
> List< double> may differ in the number of bytes needed for their fields.
> In that case, one could not know the number of bytes in the instance of
> List<any> returned from the following method:
>
> List<any> func(int input_num) {
>   if(input_num is odd)
>     return new List<int>();
>   else
>     return new List<double>();
> }

You use a getter which is implemented differently on each class.
In the case of invokedynamic, you don't even need to generate such getters
in the implementation of List<int> or List<double> because you can create
method handles that read/write fields at the expense of maybe having a
code less optimized if the number of implementations of List
(think List of different value typess) explode.

>
>
> In addition to type-independent methods such as List.size(), another
> operation that is type safe to allow on an instance of List<any> is
> wildcard capture. 

yes, very good comment !

>  Consider the generic method, swapFirstTwo, below that
> just swaps the order of the first two elements in the input list.  It is
> type safe to pass an instance of List<any> to this method (because no
> runtime type error would occur).
>
> <any T> void swapFirstTwo(List<T> list) {
>   T first = list.getAndRemoveFirst();
>   T second = list.getAndRemoveFirst();
>   list.addToBeginning(first);
>   list.addToBeginning(second);
> }
>
> Would two calls to method swapFirstTwo, one with a List<int> as input and
> the other method call with a List<double> as input, result in two
> specialized copies of method swapFirstTwo in byte code? 

yes, as far as i know there will be several specialization of swapFirstTo, but i don't think anybody as talked about wildcard capture on this list.

>  If that is the
> case, what is the byte representation of method swapFirstTwo when the input
> is an instance of List<any>?

I don't know how to implement the capture with the synthetic interface,
with invokedynamic, you first ask the class of the type parameter (the class of E for a List)
and then dispatch to the corresponding specialization.

>
>
> Thank you,
> John Altidor
> http://jgaltidor.github.io/

regards,
Rémi



More information about the valhalla-dev mailing list