Unintentional fall-through in D's switch statements
by Leandro Lucarella on 2009- 11- 21 02:34 (updated on 2009- 11- 21 02:34)- with 0 comment(s)
Removing switch fall-through from D's switch statement is something discussed since the early beginnings of D, there are discussions about it since 2001 and to the date [*]. If you don't know what I'm talking about, see this example:
switch (x) { case A: i = x; // fall-through case B: j = 2; break; case C: i = x + 1; break; }
If you read carefully the case B case A code, it doesn't include a break statement, so if x == A not only i = x will be executed, the code in case B will be executed too. This is perfectly valid code, introduced by C, but it tends to be very error prone and if you forget a break statement, the introduced bug can be very hard to track.
Fall-through if fairly rare, and it would make perfect sense to make it explicit. Several suggestions were made in this time to make fall-through explicit, but nothing materialized yet. Here are the most frequently suggested solutions:
Add a new syntax for non-fall-through switch statements, for example:
switch (x) { case A { i = x; } case B { j = 2; } case C { i = x + 1; }
Don't fall-through by default, use an explicit statement to ask for fall-through, for example:
switch (x) { case A: i = x; goto case; case B: j = 2; break; case C: i = x + 1; break; }
Others suggested continue switch or fallthrough, but I think some of this suggestions were made before goto case was implemented.
A few minutes ago, Chad Joan has filled a bug with this issue, but with a patch attached 8-). He opted for an intermediate solution, more in the lines of new switch syntax. He defines 2 case statements: case X: and case X!: (note the !). The former doesn't allow implicit fall-through and the latter does. This is the example in the bug report:
switch (i) { case 1!: // Intent to use fall through behavior. x = 3; case 2!: // It's OK to decide to not actually fall through. x = 4; break; case 3,4,5: x = 5; break; case 6: // Error: You either forgot a break; or need to use !: instead of : case 7: // Fine, ends with goto case. goto case 1; case 8: break; x = 6; // Error: break; must be the last statement for case 8. }
While I really think the best solution is to just make a goto case required if you want to fall-through [†], it's great to have a patch for a solution. Thanks Chad! =)
[†] | I find it more readable and with better locality, to know if something fall-through or not I just have to read the code sequentially without remembering which kind of case I'm in. And I think cases without any statements should be allowed too, I wonder how this works with case range statements. |