Valhalla EG notes Jan 16, 2019

Brian Goetz brian.goetz at
Tue Jan 29 20:27:35 UTC 2019

On 1/29/2019 1:55 PM, Karen Kinnear wrote:
> Brian: Could flesh out Arrays 2.0 path a bit more so we see migration costs
>     with covariance, least cognitive dissonance

As promised....

The motivation for all this is driven by the desire to compatibly 
migrate existing generic libraries (JDK and external both) to Valhalla.  
Currently, generic code has the following assumptions regarding arrays:

  - a T[] is always a subtype of Object[]
  - T[] in descriptors is erased to Bound[], usually Object[]
  - Erased descriptors show up in the wildcard type.

The following all assumes we're not heading down the array covariance 
path, and instead charts a different path.

When we allow generics to range over values, we have a problem: a 
Point[] is not an Object[].  That means a class like:

class Foo<T> {
     T[] getArray() { ... }

has a problem; if the wildcard type `Foo<?>` has its `getArray()` 
returning `Object[]`, but the underlying array is really a `Point[]`, we 
can't cast it, and we can't copy it without violating user expectations 
(for one, the identity changes.)

So the Arrays 2.0 direction here says we need a new top type for 
arrays.  Let's call it Array.

In the long run, `Array` will be a specializable generic type:

interface Array<any T> { ... }

We'll retrofit all the existing array classes to implement Array, and 
we'll change the compiler translation to erase arrays to `Array` or 
`Array<?>`, not `Object[]`.  (Sadly, because Array will not yet be 
specializable, the best we can do for now is retrofit value and 
primitive arrays to be subtypes of raw `Array`, rather than the nicer 
`Array<int>` or `Array<Point>`.)

But, now we a problem: we have existing code that erases arrays to 
`Object[]`, but after the flag day, such code will erase to Array instead.

Our solution for that problem is the full-blown solution to signature 
migration -- bridge methods, forwarding methods, and all the fancy 
handling of overriding "final" bridges as outlined in my Bridge Methods 
doc.  We'd have to emit bridges for every place we erase arrays to 
Array, which will take/return Object[] instead.

And, I could easily imagine migration pain, even with all this....

So, scorecard:

  - We'd have to have a new top type for arrays, but one that we can't 
fully make generic yet (since that requires specialization.)
- We'd have to do the full support for signature migration -- forwarding 
bridges for fields and methods, plus support for moving overrides out of 
the way when they override a "final" forwarding bridge.
  - We'd have to change how the compiler translates arrays in generic, 
and issue bridges to fix up the difference.

These are all things we'd like eventually, but we have to do them all 
now if we don't want to do covariance now.

More information about the valhalla-spec-observers mailing list