language icon indicating copy to clipboard operation
language copied to clipboard

Should we deprecate and remove support for switch case labels?

Open munificent opened this issue 1 year ago • 10 comments

The language currently allows labels on switch cases. Then you can use a continue followed by a label name to jump from one case to any other chosen case in the switch. This lets you implement state machines or other arbitrarily complex unstructured control flow bounded by the entire switch statement.

At one level, this feature is neat: It gives you a direct way to represent freeform control flow. Sort of like a bounded goto. If you want to encode a state machine directly in Dart without any trampolining and without wrapping the switch in a loop, you can.

It can also be useful for users writing tools that generate Dart code. If you are taking in some input that supports unstructured control flow and compiling it to Dart, then it may be much easier to write that compiler if you're able to have it generate a switch with labeled cases. This in contrast to, say WebAssembly, which features only structured control flow. In order to compile arbitrary C and C++ to WebAssembly, Alon Zakai and the Emscripten project had to devise a complex algorithm to tease some structured control flow out of a given arbitrary control flow graph.

However, that very expressiveness leads to a high implementation cost on the Dart team. I have heard anecdotally from many team members over the years that compiling switch case labels and labeled continues requires a disproportionate amount of effort for the amount of use users get out of them. Much of this is alreay sunk cost, but if we assume that Dart has a long prosperous future, we can assume that there will be future Dart compilers, analyzers, and other new or rewritten tools that will have to continue to pay this cost.

In particular, we seem to continually evolve Dart's use of control flow analysis for features like type promotion. Every new flow analysis ends up running into switch case labels and has to deal with them.

Does this feature carry its weight? There are two questions here:

  1. If we had a time machine, would we go back and never add them to the language in the first place? I'm fairly certain that the answer is "yes".
  2. Should we deal with the extra effort and user pain of removing them now? That's what this issue is asking.

To evaluate that, the main factors I can think of are:

  1. How much engineering effort would it take to deprecate and remove the feature?
  2. How much user pain and migration would be caused by the feature no longer being supported?
  3. What engineering resources would be freed up by no longer having to support this feature going forward?
  4. What user benefit is gained from not having to learn or encounter this feature?

I believe the answer to 4 is "almost none". I think almost all Dart users already live in a world where this feature doesn't exist because they are blissfully unaware of it.

For 1 and 3, we can and should ask the implementation teams.

For 2, we can get some data on this by looking at code in the wild to see how often the feature is used. I scraped 2,000 pub packages and of the 805 switch statements, I found exactly one that used labels:

      switch (widget.placement) {
        case ToolbarPopupPlacement.start:
          if (directionality == TextDirection.rtl) {
            return ToolbarPopupPlacement.end;
          }
          continue next;
        case ToolbarPopupPlacement.end:
          if (directionality == TextDirection.rtl) {
            return ToolbarPopupPlacement.start;
          }
          continue next;
        next:
        default:
          return widget.placement;
      }

You will note that this code would be exactly the same length if the continue next; lines were simply replaced with return widget.placement;. I wouldn't consider this a very compelling use.

munificent avatar Nov 01 '23 23:11 munificent