Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is lub(null, Double)?

Table 15.25-B in JLS version 8 says that the type of a conditional expression

true ? null : 0.0

is lub(null,Double), where lub appears to be some crazy incomprehensible thing from section 4.10.4.

This appears to be distinct from the Double type somehow, or they probably would have just written Double, like they did elsewhere in the table. It's not clear what the difference could be, though. I tried to work it out from section 4.10.4, but by the time I got to the part about

Let lub(U1 ... Uk) be:

Best(W1) & ... & Best(Wr)

it seemed like they were saying that this type is an intersection type of the null and Double types, which makes no sense.

What is lub(null, Double)? How does a conditional expression with this type behave differently from if its type were just defined as Double?

like image 870
user2357112 supports Monica Avatar asked Apr 19 '17 21:04

user2357112 supports Monica


2 Answers

It's just Double.

Informally, lub(null, Double) is (a decent approximation to) the most specific type that contains all values of the null type and the Double type, and the most specific such type is Double.

Formally, we can work through the definition of lub in JLS section 4.10.4, and we find that lub(null, Double) is Double:

The least upper bound, or "lub", of a set of reference types is a shared supertype that is more specific than any other shared supertype (that is, no other shared supertype is a subtype of the least upper bound). This type, lub(U1, ..., Uk), is determined as follows.

If k = 1, then the lub is the type itself: lub(U) = U.

Otherwise:

For each Ui (1 ≤ i ≤ k):

Let ST(Ui) be the set of supertypes of Ui.

ST(null) is the set of all reference types, and ST(Double) is {Object, Number, Double}.

Let EST(Ui), the set of erased supertypes of Ui, be:

EST(Ui) = { |W| | W in ST(Ui) } where |W| is the erasure of W.

EST(null) is the set of the erasures of all reference types, and EST(Double) is {Object, Number, Double}.

Let EC, the erased candidate set for U1 ... Uk, be the intersection of all the sets EST(Ui) (1 ≤ i ≤ k).

EC is the intersection of EST(null) and EST(Double), so EC is {Object, Number, Double}.

Let MEC, the minimal erased candidate set for U1 ... Uk, be:

MEC = { V | V in EC, and for all W ≠ V in EC, it is not the case that W <: V }

MEC is the set of all types in EC that have no proper subtype in EC. Double is a proper subtype of both Number and Object, so MEC = {Double}. (W <: V means that the type W is a subtype of the type V. A type is considered a subtype of itself, so they specify W ≠ V to count only proper subtypes.)

For any element G of MEC that is a generic type:

[lots of text]

MEC contains no generic types, so we can skip this.

Let lub(U1 ... Uk) be:

Best(W1) & ... & Best(Wr)

where Wi (1 ≤ i ≤ r) are the elements of MEC, the minimal erased candidate set of U1 ... Uk;

and where, if any of these elements are generic, we use the candidate parameterization (so as to recover type arguments):

Best(X) = Candidate(X) if X is generic; X otherwise.

Candidate was defined in the part we skipped; we can still skip it, since it only matters for generic types.

lub(null, Double) is Best(Double), and Best(Double) is Double, so lub(null, Double) is Double.

like image 164
user2357112 supports Monica Avatar answered Nov 04 '22 14:11

user2357112 supports Monica


I believe that lub(null, Double) === Double. Not sure why use lub(null, Double). Maybe to allow for change in the semantics of the null type in the future?

Here's my reasoning. By definition, LUB = lub(T_1, ..., T_n), the Least Upper Bound of types T_1,...,T_n, is a type that is a supertype of all T_1, ..., T_n such that there's no proper subtype of LUB that is also a supertype of all T_1,...,T_n (ie, it's the most specific type that's simultaneously a supertype of T_1,...,T_n).

By definition, the type of the null expression is the null type. Also by definition, all reference types except the null type are direct supertypes of the null type.

Double is a supertype of the null type. Double is also a supertype of itself, the Double type. So Double does satisfies the condition is a supertype of all T_1,...,T_n. On the other hand, there's no other type that can be a proper subtype of Double and still be a supertype of Double. Hence, Double is the lub(null, Double).

like image 25
Bruno Reis Avatar answered Nov 04 '22 13:11

Bruno Reis