Nullity (was: User model stacking: current status)

Brian Goetz brian.goetz at oracle.com
Thu May 12 12:22:06 UTC 2022


> Here is my current concept of this beast:
>

The next installment of this is: how does assignment and conversion 
work?  Presumably, it starts with:

  - there is a null-discarding conversion from T? to T! (this is a 
narrowing conversion)
  - there is a nullability-injecting conversion from T! to T? (this is a 
widening conversion)

and then we get to decide: which conversions are allowed in assignment 
context?  Clearly a nullability-injecting conversion is OK here 
(assigning String! to String? is clearly OK, it's a widening), so the 
question is: how do you go from `T?` to `T!` ? Options include:

  - it's like unboxing, let the assignment through, perhaps with a 
warning, and NPE if it fails
  - require a narrowing cast

> Enter Valhalla:
>
> * (Let's say we have B1, B2a/B3a (atomic), and B2b/B3b ("b"reakable?))
> * On a B3 value type like `int`, `?` would be nonsense and `!` redundant.
> * That's equally true of a B3 value type spelled `Complex.val` (if 
> such a thing exists).
> * (assuming `Complex` is ref-default) all three of `Complex`, 
> `Complex?`, and `Complex!` have valid and distinct meanings.

If we have both .val and nullity annotations I think we are losing. The 
idea here would be that B3.val *is literally spelled* `B3!`. The 
declaration story is unchanged: class B1 / value-based class B2 / [ 
non-atomic ] value class B3, for some suitable spellings.

> Now, imagining that we reached this point... would B3a/B3b (as a 
> language-level thing) become immediately vestigial?.

Unfortunately not.  We need permission to unleash the zero-default type, 
because many B2 types (e.g., LocalDate) have no good zero.  So B3 is 
needed to unlock that.

> With Complex as a B2a or B2b, would `Complex!` ever not optimize to 
> the B3-like *implementation*? I think the (standard) primitives could 
> be understood as B2 themselves, with `int` just being an alias for 
> `Integer!`.

A B3:

     value class Integer { ... } // int is alias for Integer!

What this short discussion has revealed is that there really are two 
interpretations of non-null here:

  - In the traditional cardinality-based interpretation, T! means: "a 
reference, but it definitely holds an instance of T, so you better have 
initialized it properly"
  - In the B3 interpretation, it means: "the zero (uninitialized, 
not-run-through-the-ctor) value is a valid value, so you don't need to 
have initialized it."

>     Con: To the extent full emotional types do not align clearly with
>     primitive type projections, we might be painted into a corner and
>     it might be harder to do emotional types.
>
>
> I'm questioning whether we would need primitive type projections at 
> all, just nullable/non-null type projections.

Indeed, that was the point of my query.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/valhalla-spec-experts/attachments/20220512/4f1cfa27/attachment.htm>


More information about the valhalla-spec-experts mailing list