Letting the nulls flow (Was: Exhaustiveness)

Brian Goetz brian.goetz at oracle.com
Sun Aug 23 20:31:09 UTC 2020


> Note that if we keep "default", it has to accept null because fundamentally, "default" is like "else".

I agree on default, and I also agree on the comparison to `else`. Which 
underscores the importance of totality here; a switch:

     case Frog f:
     case Tadpole t:
     default / case var x / case _ / case Object o / ... any of these, 
they're all total

is really equivalent to the if-else chain:

     if (x instanceof Frog f)  { ... }
     else if (x instanceof Tadpole t) { ... }
     else { ... }

... *precisely because* the patterns in the last line are total.  In 
other words, a total pattern in a switch is like the `else` of an `if` 
(and like with `if`, nothing can come after an unqualified `else` 
clause, because it would be dead.)  I believe this is the analogy you 
are looking for in the comments above about refactoring between switch 
and if chains; if the pattern is a "no op", when refactoring to/from an 
if-else chain, the "no op" pattern maps to the else clause.

(Note that we already see this nod to totality elsewhere in the 
language, too; we distinguish between static casts, unchecked casts, and 
dynamic casts, based on ... wait for it ... totality.  If the "test" in 
question is total, that affects the semantics of the "test", such as 
what exceptions it may throw.)

> For a destructuring pattern on Foo, if there is no "case Foo(null)", "case Foo(var x)" (or case var x at the top-level/or default), i don't see why this pattern has to accept "null" when destructutring because the switch will not know what to do with that null. Raising a NPE the earliest seems the right semantics for me.

I am not sure exactly what you are saying here.

     case Foo(var x)

alwyas matches Foo(null), but it only matches `null` itself when 
`Foo(var x)` is total on the target type (IOW, when the pattern test is 
a no-op.)


> I tried the usual jedi mind trick to convince you that a statement switch doesn't have to behave like a legacy switch but my force power doesn't seem to work through internet.

It was a good try, you made me think for a few minutes.
> In that case, i suppose we can choose among the solutions proposed by Guy to get a statement switch which has no implicit "default".

Let's be careful to separate the "optimistically total" feature (in the 
presence of sealing) from the base switch semantics.  I think the base 
switch semantics are quite simple now -- we carve out legacy behavior 
for three kinds of types (enums, strings, and boxes), and then switches 
are 100% null-friendly after that.

Scaling optimistic totality to sealed classes wrapped in deconstruction 
patterns looks like it is going to require more work, but I think that's 
a separate problem.




More information about the amber-spec-experts mailing list