[pattern-switch] Opting into totality

Brian Goetz brian.goetz at oracle.com
Fri Sep 4 11:08:37 UTC 2020

I agree with the “unpleasant asymmetry” part, but I’m not sure its fair to call it arbitrary.  The original design of switch statements deliberately embraced partiality, for non-arbitrary reasons; the design of expression switches deliberately embraced totality, again for non-arbitrary reasons (and with awareness of the ensuing asymmetry.)  I think it is more accurate to attribute the asymmetry not to arbitrary choices, but deliberate ones, specifically: the decision to reform switch, rather than create a new-and-almost-identical-but-not-identical construct (“snitch”), and have the two (or four or eight, as we discovered new mistakes) live side-by-side forever.  And, while there were many “quick-lets-fix-the-mistakes-of-the-past" suggestions for the ideal snitch semantics, I suspect that had we designed a snitch in 12, we still would have faced uncomfortable evolutionary challenges now.  (For the record: I am still convinced that reform, rather than replacement, is the right move.)  

We knew the cost would be some asymmetries and some uncomfortable special cases (such as the current quarantining of preemptive null-hostility to the three legacy reference target types, enums/strings/boxes.)  But these costs are still far lower (IMO) than having two almost-the-same-but-not constructs living side-by-side forever, a burning hulk by the side of the road that is never extinguished.  At some level, the current discussion is an exploration of how much of our cake we can have and eat as well. 

When we did expressions switches, we knew the totality asymmetry was not a solved problem.  For the limited sorts of non-strongly-total switches we had then (just enum switches), doing nothing at the time, and keeping the option to do something later, was the obvious and right move.  As switches get more powerful, there are more kinds of non-strongly-total switches (switches over sealed types, switches with deconstruction patterns lifted over total pattern groups, etc), and the desire for some extra type checking (and automated remainder handling) becomes greater.  

For the current round (type patterns in switch), I think its probably practical to still do nothing now; I think the real need comes around when we get to deconstruction and nested patterns.  But none of the options discussed are perishable; the things that are compatible now will be compatible later, and the things that are incompatible now will still be incompatible later.  

> I just want to interject that I really dislike the terminology (and therefore the syntax) “sealed switch” because it is too likely to confuse Joe Programmer (or me) into thinking that it necessarily makes use of, or is used in conjunction with, a sealed type.  One might also misconstrue it to mean that the set of switch labels is fixed and cannot be added to later!

I agree that the reuse of “sealed” here is in the clever-possibly-too-clever category, and am happy to keep searching for something better.  I’ll just reiterate that there is a nice accidental connection to sealed-ness — that such switches are not “leaky”.  Sealing a switch means that there will be no values that are passed through and not acted upon.  

I bring this up again not to defend the syntax, but to underscore a more important point: that we thought at first that “sealing” switches was about asserting totality and enlisting the compiler’s aid in verifying same, but as we worked through the cases, and discovered there were more cases of remainder than we initially thought, the main value of sealing instead became restoring the switch to having no unhandled remainder.  Whatever syntax we choose should try to evoke that at least as much as evoking totality of the case labels.  

> On Sep 3, 2020, at 10:24 PM, Guy Steele <guy.steele at oracle.com> wrote:
> There is currently a fundamental unpleasant asymmetry caused by the arbitrary decision to require that all switch expressions be total but not all switch statements be total.
> As we have added other options, the design space still has an unpleasant asymmetry (or lack of orthogonality) because of that original decision.
> We have two choices: (a) recant that original decision, or (b) live with the asymmetry.
> As I have already pointed out, (a) is certainly possible and completely consistent; all you have to do is return default values for the cases that are not covered.  Then the choice of switch-versus-expression is completely independent of the choice of regular-switch versus total-switch.  The likely result is that authors and IDEs will warn programmers that they should NEVER EVER use a non-total switch expression, so it seems silly to expand the design space to provide a combination of features that should never be used.  (“What, never?”  “Well, hardly ever.”)
> The other choice, which is what Rémi and Brian have been discussing for the last week, is not whether to get rid of the asymmetry, but merely debating exactly what its shape should be.
> A possibility I don;’t think I have yet seen offered is that we should, as before, require switch expressions to be total, but also, in an incompatible move, require switch expressions to use whatever `total-switch` syntax is adopted.
> In such a scenario, perhaps we really are trying to move the world to `snitch` after all, and we’re just arguing about the least disruptive spelling for it.
> —Guy

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20200904/6fdeb95a/attachment-0001.htm>

More information about the amber-spec-experts mailing list