a new contract for reference types

Peter Levart peter.levart at gmail.com
Sat May 11 19:50:18 UTC 2019


On 5/8/19 7:16 PM, John Rose wrote:
> On May 7, 2019, at 11:37 PM, Peter Levart <peter.levart at gmail.com> wrote:
>> On 5/2/19 12:29 AM, John Rose wrote:
>>> Regarding subtyping, I don't see (from these considerations)
>>> a firm reason to declare that V? is a super of V.  The value
>>> set of V?*might*  have one more point than that of V,
>>> or it*might not*.  The reason we are doing V? is not the
>>> value set, but the whole contract, which includes the
>>> value set as an obvious, but ultimately non-determinative part.
>> Just one observation...
>> If inline class V was declared to support a "kind" of null (default, sentinel) value by itself, then how such value would be denoted?
>> Is this a way?
>> V v = null;
> Yes, because there's only one null in the whole world.
> (The possibility of having many kinds of null, perhaps
> one per type, is something we are trying to avoid.
> Null is a costly feature, sometimes referred to as a
> billion dollar mistake[1].  We have to deal with it
> in Java.  Adding more of them would be even more
> costly IMO.)
> [1]: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare

A really good and though provoking talk. In particular I liked the part 
where Tony Hoare compares flow control abstractions in high level 
languages (loops, if-then-else, exceptions) with data structure 
abstractions. The machine level building block for the first is jump 
instruction, while for the second a pointer.

While there are several different flow control abstractions, there's not 
much that is abstracted about pointers in high level languages. V vs. V? 
seems to be an abstraction in that direction that is just approximately 
tied to the machine level implementation.

So a question arises whether to allow calling instance methods on null V 
or to runtime check for null (sentinel) value and throw NPE at call site.

Since null (sentinel) value of null capable V is represented by a real 
state, it should be possible for instance methods to operate on that 
state, but...

>> If this was possible, then what would be the distinction between the following two then?
>> V? vInd1 = null;
>> V? vInd2 = v;
>> Would vInd1 and vInd2 represent the same "null" value?
> Yes, please please please.

... what should be the outcome of invoking an instance method on a null 
V? then?

If you allow calling instance method on a null V:

V v = null;

v.m(); // OK

Then the following becomes confusing for the user:

V v = null;

v.m(); // OK

V? vInd = v;

vInd.m(); // NPE or OK ?

You might implement the 2nd call to operate on a re-constructed null 
(sentinel) state of V in that case, but then throwing NPE or not becomes 
a matter of whether V is null-sentinel capable or not, because you can 
not construct null state when V does not declare that capability.

So the only consistent behavior seems to be to always throw NPE on null, 
which might involve runtime check for null sentinel state.

Regards, Peter

More information about the valhalla-spec-experts mailing list