More on this: we’ve ambled our way into a nice and consistent model for “?” types. Which is, T? is the union type of T and Null. This works for nullable values: (V? where V is a zero-default value type), type variables (T? means T union Null), and also for nullable type patterns (the pattern Foo? matches any non-null Foo, or null.).
This is not necessarily what users will immediately think T? means, especially if they’ve got experience with type systems where ? is an arity indicator meaning “zero or one” (such as X#/C_omega). But its an explainable and stable thing, and the fact that we independently came to this from two directions (values and patterns) is an encouraging indicator. > On Apr 26, 2019, at 9:44 AM, Brian Goetz <brian.go...@oracle.com> wrote: > > I’ve been looking over Chapter 18 (thanks Dan!) and it seems that we are > almost there to defining inference to work properly for values and erased > generics. > > There is already a _null type_, and we’ve defined it so that for every > reference type R, Null <: R (JLS 4.10.). In order to make inference work for > nullable values, we need to state that for a zero-default value type V: > > Null <! V > Null <: V? > > and that LUB(V, Null) = V? > > When we gather constraints in 18.1, in addition to adding the upper bound on > alpha, we also add in lower bounds Null <: alpha_i for erased type vars. > > We adjust 18.4 to not consider Null to be a proper lower bound for purposes > of resolution. > > Simple example: > > Point p; > var v = new Box<>(p); > > We gather bounds alpha <: Object (from the declaration of Box<T>), Point <: > alpha (from the argument), and Null <: alpha (T is an erased type var), > yielding > > Null, Point <: alpha <: Object > > By 18.4, alpha = LUB(Point, Null) = Point?. > > Obviously this is only one example, and there’s a bunch of work to thread > this all the way through Ch18 (good luck Dan!), but it seems to me that the > underpinnings are here already. > >