- Proposal: SE-NNNN
- Author(s): Jacopo Andrea Giola
- Status: Review
- Review manager: TBD
Since the beginning of the Swift public beta, the switch
statement
was a safer evolution of the C-style switch
, disallowing
the implicit fall through behavior between cases, and introducing the fallthrough
keyword forcing the developers to explicitly require it.
This proposal wants to improve the switch
statement by substituting the
fallthrough
keyword with a more secure and powerful fallto
.
In C the switch
construct can be applied only to integers or enum
s,
every case must be declared separately and there is no way to specify a where
clause
for adding additional conditions.
With this landscape the fall through behavior has less impact on the safety of execution
of the code inside it, unless if the behavior is for a missing break
statement.
In Swift the switch
control flow is greatly improved,
it can be called against pretty much every type and the various cases can specify a value,
a range of values, or more complex matching patterns;
it gives even a where
clause to check for additional conditions.
Every one of this new features in Swift makes the switch
statement more flexible,
powerful and safe of the old C-style of which retain the name.
With this in mind the fallthrough
keyword seems an old relic
that is here only for easing the translation of C and Obj-C code to Swift.
fallthrough
can lead to subtle bugs that were not possible in C
and that for a novice of the language can be seen as odd.
The major complaint against fallthrough
is the next excerpt from
The Swift Programming Language (Swift 2.1):
NOTE
The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior.
As you can read, fallthrough
skip the case specified underneath it altogether without checking it,
even if it's specifying a where
clause.
So in a trivial example like this:
let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
// do something
x = 10
fallthrough
case .Two where x >= 0 && x < array.count:
element = array[x];
case .Three:
// do something else
default:
break;
}
This code will compile fine but crashes at runtime for someEnumeration = .One
.
The developer might even had introduce this bug later on
because it has refactored the x control from inside the .Two
case to the where
.
Another pitfall of fallthrough
can be related to wrong refactoring of the code
that moves around the cases declaration (maybe for a merge gone wrong)
and until runtime the bug can't be spotted without manual review.
The proposed solution is to change the fallthrough
keyword to fallto
.
This new keyword will accept an explicit value
that must be matched with one of the following cases.
The associated where
clause of the case will be evaluated and if it fail
the code will exit the switch.
let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
// do something
x = 10
fallto .Two
case .Two where x >= 0 && x < array.count:
element = array[x];
case .Three:
// do something else
default:
break;
}
In doing so, we can even have a nice flow improvement; we can have two diverse cases fall inside a third one.
let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
// do something
x = 10
fallto .Three
case .Two where x >= 0 && x < array.count:
element = array[x];
fallto .Three
case .Three:
// do something else
default:
break;
}
If the case specified can't be matched against one of the following ones
(default
is a special case and it can be targeted only specifying default
)
It will be a compile error.
The impact in the existing code will be minimum. An automated translation from fallthrough
and the new syntax can be automated for the switch cases with a single defined value
in the case next to fallthrough
.
For the more complex cases the developer will have to manually change the code.
One of the alternative considered for this functionality was a reswitch
keyword
that will reevaluate the entirety of the switch construct
with the new value passed by the developer.
One major flaw of this approach is that can lead to transform the switch control flow in a kind of loop construct and will introduce all the problems associated with it, mainly infinite loop errors.
- Proposal: SE-NNNN
- Author(s): Jacopo Andrea Giola
- Status: Review
- Review manager: TBD
Since the beginning of the Swift public beta, the switch
statement
was a safer evolution of the C-style switch
, disallowing
the implicit fall through behavior between cases, and introducing the fallthrough
keyword forcing the developers to explicitly require it.
This proposal wants to improve the switch
statement by substituting the
fallthrough
keyword with a more secure and powerful fallto
.
In C the switch
construct can be applied only to integers or enum
s,
every case must be declared separately and there is no way to specify a where
clause
for adding additional conditions.
With this landscape the fall through behavior has less impact on the safety of execution
of the code inside it, unless if the behavior is for a missing break
statement.
In Swift the switch
control flow is greatly improved,
it can be called against pretty much every type and the various cases can specify a value,
a range of values, or more complex matching patterns;
it gives even a where
clause to check for additional conditions.
Every one of this new features in Swift makes the switch
statement more flexible,
powerful and safe of the old C-style of which retain the name.
With this in mind the fallthrough
keyword seems an old relic
that is here only for easing the translation of C and Obj-C code to Swift.
fallthrough
can lead to subtle bugs that were not possible in C
and that for a novice of the language can be seen as odd.
The major complaint against fallthrough
is the next excerpt from
The Swift Programming Language (Swift 2.1):
NOTE
The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior.
As you can read, fallthrough
skip the case specified underneath it altogether without checking it,
even if it's specifying a where
clause.
So in a trivial example like this:
let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
// do something
x = 10
fallthrough
case .Two where x >= 0 && x < array.count:
element = array[x];
case .Three:
// do something else
default:
break;
}
This code will compile fine but crashes at runtime for someEnumeration = .One
.
The developer might even had introduce this bug later on
because it has refactored the x control from inside the .Two
case to the where
.
Another pitfall of fallthrough
can be related to wrong refactoring of the code
that moves around the cases declaration (maybe for a merge gone wrong)
and until runtime the bug can't be spotted without manual review.
The proposed solution is to change the fallthrough
keyword to fallto
.
This new keyword will accept an explicit value
that must be matched with one of the following cases.
The associated where
clause of the case will be evaluated and if it fail
the code will exit the switch.
let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
// do something
x = 10
fallto .Two
case .Two where x >= 0 && x < array.count:
element = array[x];
case .Three:
// do something else
default:
break;
}
In doing so, we can even have a nice flow improvement; we can have two diverse cases fall inside a third one.
let array = [1, 2, 3];
var element = 1;
switch someEnumeration {
case .One:
// do something
x = 10
fallto .Three
case .Two where x >= 0 && x < array.count:
element = array[x];
fallto .Three
case .Three:
// do something else
default:
break;
}
If the case specified can't be matched against one of the following ones
(default
is a special case and it can be targeted only specifying default
)
It will be a compile error.
The impact in the existing code will be minimum. An automated translation from fallthrough
and the new syntax can be automated for the switch cases with a single defined value
in the case next to fallthrough
.
For the more complex cases the developer will have to manually change the code.
One of the alternative considered for this functionality was a reswitch
keyword
that will reevaluate the entirety of the switch construct
with the new value passed by the developer.
One major flaw of this approach is that can lead to transform the switch control flow in a kind of loop construct and will introduce all the problems associated with it, mainly infinite loop errors.