Idea how to implement VT/VO compatibility in JVM

Peter Levart peter.levart at gmail.com
Wed Jan 28 21:56:09 UTC 2015


On 01/22/2015 02:26 PM, Maurizio Cimadamore wrote:
>
> On 22/01/15 13:19, Vitaly Davidovich wrote:
>> Can you expand a bit on the part where you say frameworks can't 
>> iterate a
>> Collection<any T> without knowing the instantiation? Do you mean 
>> existing
>> methods that take Collection<?> won't work without change or 
>> something else?
> In the current prototype, such methods will work, but they will work 
> with all reference-parameterizations - example:
>
> void m(Collection<?> c) { ... }
>
> List<String> ls = ...
> List<Object> lo = ...
> List<int> li = ...
> List<MyPointValue> lmpv = ...
>
> m(ls); //ok
> m(lo); //ok
> m(li); //fail, List<int> is not subtype of Collection<?>
> m(lmpv); //fail, List<MyPointValue> is not subtype of Collection<?>
>
> In other words, Collection<?> means Collection<? extends Object>. 
> Therefore, primitives and values are outside the domain supported by 
> the unbounded wildcard.
>
> To fix that, you need to change 'm' as follows:
>
> <any T> void m2(Collection<T> c) { ... }
>
> m(ls); //ok
> m(lo); //ok
> m(li); //ok
> m(lmpv); //ok
>
> Is this what you were asking?
>
> Maurizio

There could also be an abbreviation:

void m3(Collection<any ?> c) { ... }

...which would be equivalent to m2 above, but used only if you don't 
need T in the method (you only invoke methods on 'c' that are not 
mentioning T from Collection<any T> in their signature, such as size(), 
clear(), ...). Maybe you could also call methods, that mention T in 
return type, but you could not assign the result to anything (or maybe 
to Object in certain situations), for example:

class Foo<any T> {

     T getOne() { ... }

     Optional<T> getMaybe() { ... }

}


void m4(Foo<any ?> anyFoo) {

     anyFoo.getOne(); // can call, but not use the result

     Object r = anyFoo.getMaybe(); // can assign to Object since 
Optional<?>, Optional<int>, etc. are all Objects

}

(I'm still considering Optional as reference type here)

Peter


>
>>
>> sent from my phone
>> On Jan 22, 2015 8:12 AM, "Stéphane Épardaud" <stef at epardaud.fr> wrote:
>>
>>> On 01/22/2015 12:18 PM, Maurizio Cimadamore wrote:
>>>
>>>> I don't think there's an 'hole' as such in your proposal - but 
>>>> there are
>>>> 'unknowns'.
>>>>
>>> Well, that's already good news. I prefer unknowns to known holes ;)
>>>
>>>   Performance-wise, I think the 'risk' is that if we keep the API 
>>> the way
>>>> they are today (i.e. removeAll(Collection<?>) and friends), the 
>>>> boxing path
>>>> will pretty much be the norm. Now, in a perfect world, as value 
>>>> types are
>>>> non-polymorphic (or their polymorphism is very restricted) and 
>>>> immutable,
>>>> that would suggest that VM should have enough of an hint to perform 
>>>> boxing
>>>> elimination and such, so that the cost you end up paying is 
>>>> negligible. How
>>>> much of this is reality? As you, I'm not a VM guru - but I think 
>>>> it's a
>>>> question worth asking. It seems a likely scenario that the JVM will do
>>>> great in most cases, and have some bad performance cliffs in others 
>>>> - is
>>>> that something we are willing to sign up for?
>>>>
>>> OK, that's fair. By allowing people to use value types boxed we 
>>> allow them
>>> to shoot themselves in the foot perf-wise (assuming the VM can't help),
>>> because we make value types much more accessible. This is mostly due to
>>> `any T` being opt-in rather than the new default for `T` where `T 
>>> extends
>>> Object` is not specified. If we also changed `T` to mean `any T` 
>>> (source
>>> only, so for newly compiled code) then all generics code would be
>>> specializable by default and that means that users of generic code will
>>> always be able to use the specialised code as long as they can 
>>> instantiate
>>> the generic type argument at compile-time (as is already the 
>>> limitation).
>>> If they can't, well they already have to use `Object` and boxing and 
>>> can't
>>> traverse collections because they're not `List<Object>` (ATM).
>>>
>>> Making it the default has down sides, probably in larger class 
>>> files, but
>>> as long as it's not the default, there will always be 
>>> incompatibilities in
>>> libraries that will forget to opt-in, which will mean that either (ATM)
>>> they can't be used with containers of value types, or that the 
>>> containers
>>> have to be wrapped to box the value types (unless we fix that as I
>>> suggest). IMO that's already going to cause compatibility issues and 
>>> there
>>> may arise a "coding guideline" (remember them from C++ sore points?) 
>>> that
>>> people will be strongly encourage to use `val T` everywhere just in 
>>> case
>>> someone wants to use an unboxed value type.
>>>
>>> The rift between primitives and Object is already a famous sore 
>>> point in
>>> Java (not criticising, this was a choice made a long time ago, for 
>>> valid
>>> reasons, we just have to deal with it) which has been "fixed" in most
>>> non-Java JVM-languages due to popular demand. I don't think the new 
>>> default
>>> with value types should be that generics don't accept value types.
>>>
>>>   On the language-side unknowns, how much code out there is relying on
>>>> being able to access fields on Foo<?> or raw Foo types? This is 
>>>> perhaps not
>>>> common, but I think we need to gather data points on this i.e. by 
>>>> looking
>>>> at existing open source projects (help welcome here!). Other 
>>>> possible weak
>>>> points are that this doesn't necessarily address all the issue w.r.t.
>>>> language uniformity - i.e. how is an ArrayList<int> supposed to 
>>>> answer to a
>>>> question of the kind 'is instance of List<?>' ?
>>>>
>>> Fields that don't involve the `any T` are fine. Fields that do may 
>>> have to
>>> revert to autoboxing _if_ we feel we _must_ accomodate that to 
>>> autobox not
>>> just value types but their containers.
>>>
>>> `ArrayList<int>` is special, mostly due to the fact that I'm not 
>>> sure we
>>> can retrofit `Integer` to be a value type, so existing primitives 
>>> may not
>>> get the `List<int> === List<Integer>` that I suggest for value types
>>> (though I'd be very interested in making this work).
>>>
>>> If we take an easier example assuming a value type named `Date`, 
>>> then yes
>>> I expect that:
>>>
>>> - `List<val Date> instanceof List<?>` == `true`
>>> - `List<__Boxed Date> instanceof List<?>` == `true`
>>>
>>>   I'm not denying there's something there worth exploring (as I have in
>>>> fact already said), but it seems to me that, while you can go a 
>>>> long way
>>>> with bridges, there are still questions that bridges alone simply 
>>>> do not
>>>> have an answer for.
>>>>
>>> Thanks, and yes I agree there are still questions remaining, and more
>>> importantly an implementation lacking, but hopefully if the proposal 
>>> sounds
>>> decent I can help with the proto.
>>>
>>> Thanks for your answers BTW :)
>>>
>



More information about the valhalla-dev mailing list