# [External] : Re: Primitive values and void

John Rose john.r.rose at oracle.com
Tue Feb 23 18:20:28 UTC 2021

```On Feb 17, 2021, at 8:59 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
> On 2/16/2021 9:08 PM, Nir Lisker wrote:
>>
>>    There's a certain amount of accidental complexity that will have
>>    to be compounded to get there; for example, there are "statement
>>    lambdas" and "expression lambdas" but if void is a type, then a
>>    statement lambda could also be an expression lambda returning
>>    void.  I doubt any of these are blockers, but there's a certain
>>    amount of un-fun grinding here to clear out the underbrush.
>>
>>
>> This made me think of cases of the so-called "ternary expression" that doesn't work with `void`:
>>
>> boolean b = i == 3 ? boolean1() : boolean2();
>> ??? = i ==3 ? void1() : void2();
>
> Indeed, this is the sort of accidental complexity that would have to either deal with `void` as a new type, or be adjusted to explicitly disallow void expressions in either of the arms.  None of this is likely to be impossible, just tedious.
>
>> where the methods return `boolean` and `void`. While I understand that the point is assignment, and that assigning to `void` is meaningless, we can still assign to technically `Void`. Probably, the only reason to deal with this is if we accept the "ternary expression" as a full shortcut to if-else, and not only to if-else assignments. This is probably too far off the mark though.
>
> I think the logical way to look at this is to let the construct define how it handles void or not, and then treat Void as the box for void, just as we treat Integer as the box for int.  (Boxing conversions will get adjusted as part of Valhalla, but the concept will still be around.)

If Void were a regular reference-box for a primitive value void,
then the range of the type Void contains two values, reference
null and the single value of the (unit type) void.  But, unlike,
other wrappers, there is nothing *other than* the remainder
value null in Void.  This is an irregularity when trying to make
Void be a wrapper for (unit type) void.  It’s not a deal-killer,
but more annoying un-fun underbrush to cut away.  Do we
keep the irregularity, or add a second primitive void value?

Or we could say (by ad hoc fiat) that (Void)null interconverts
to the void value (not otherwise denotable as a reference).
That’s the approach that method handle conversions takes
(in explicitCastArguments).

Just saying…

— John

P.S. One more thing:  Void also *acts like* a nullable reference-box
type for a primitive type with *zero* value points, also known
as an “empty type” or “impossible type”.  That hypothetical
primitive type (call it “Unreached”?) denotes:

- the return type of a method which must never return normally
- parameter type of a method which must never be called
- the field type of an class/species which must never be instantiated
- a local variable in a declaration which must never complete normally

Of course if you adjoin null to that empty type you get a one-point
reference type containing only null, just like Void.

(I’m *not* saying that Void is a candidate name for “Unreached”.)

```