Make all switches exhaustive?
Brian Goetz
brian.goetz at oracle.com
Tue Apr 27 17:11:18 UTC 2021
Maurizio's comment got me thinking about a possible way to eliminate the
sharp edge of "sometimes switches are type-checked for exhaustiveness,
and sometimes not."
Historically, there is no requirement that switches be exhaustive;
legacy switches without a default are like unbalanced ifs. (Notably,
though, the DA rules do distinguish between switches with and without a
default, and switches implicitly reject any null remainder -- so we
still do have a solid base to build on here.)
When we did expression switches, we said "expression switches must be
total." This was a forced move if we wanted to reuse "switch", because
expressions must be total and compatibility backed us into letting
statement switches be partial. Unfortunately, this leaves statement
switches with less type checking than expression switches, since there
is no way to even opt into exhaustiveness checking.
As switch gets more powerful (e.g., switching over sealed types with
patterns), this lack of exhaustiveness checking becomes a bigger deal.
We'd been imagining that we'd have to "patch" switch to allow opting
into exhaustiveness checking, but maybe there's another way.
As we are about to dramatically extend the power of switch (by
permitting pattern labels, and allowing switches on other types than
integers, boxes, strings, and enums), what we could do is:
- Erroring on non-exhaustive non-legacy statement switches now;
- Warning on non-exhaustive legacy statement switches now;
- Later upgrading these warnings to errors, after a period of time
where people can update their code.
The world we end up in in the long run is: all switches are exhaustive,
with no new language surface for managing exhaustiveness.
Legacy switches are those whose operand type is one of the "classic"
types and all labels are constant labels or "default".
For a switch that is deliberately non-exhaustive, all the user has to do
to capture this (and shut up the compiler) is:
default: break;
which is not very intrusive, and arguably makes the code more readable
anyway. Users will see a speed bump when upgrading to pattern switches
(clippy will tell them "I see you're writing a pattern switch, don't
forget to end it with default:break") which presumably they will quickly
internalize.
(How's that for teaching an old dog new tricks?)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20210427/1190f3b0/attachment.htm>
More information about the amber-spec-experts
mailing list