Regarding this section of the error handling rationale:
It is valuable to be able to overload higher-order functions based on whether an argument function throws
What it means is that functions should be overloadable based on whether an argument with a function type throws, not based on whether the function itself throws. Consider this function:
func execute<R>(_ function: () throws -> R) rethrows -> R {
return try function()
}
The above function is actually syntactic sugar over the following two functions:
func execute<R>(_ function: () -> R) -> R {
return function()
}
func execute<R>(_ function: () throws -> R) throws -> R {
return try function()
}
These two functions more clearly demonstrate that they are overloaded based on whether their argument throws, which is distinct from them being overloaded based on whether the function itself throws. (The rethrows keyword is actually how Swift discourages a pattern of duplication.) In fact, the same section of the error handling rationale says
It shouldn't be possible to overload functions solely based on whether the functions throw.
I believe that this is so that the try operator can be applied to subexpressions and to make Swift’s chosen overload more clear.
try (try executeThrowingMethod()).executeAnotherThrowingMethod()
// if the `try` operator couldn’t be applied to subexpressions, then code like this could become very verbose
Logic errors are possible to handle, though. In fact, Swift expects these errors to be handled by the programmer.
I don’t think bound checks are common enough in code for this proposal to make a noticeable impact in clarity — most of the time, an Array index will be derived from the Array itself. In fact, I think this change could reduce clarity, as it would make it harder to figure out which overload of a function is called. It would also mean we’d either have use the try operator much more, or we’d have to start applying (and remembering to apply) a donttry operator.
Another aspect of crashing upon a logic error is performance: logic errors may have to be checked many times while a program’s is running, so speed is very important in this context. Crashing upon a logic error helps offset the overhead of these checks. (I don’t believe the Swift team has ever told us why this is, but I assume it’s because it may enable certain compiler optimizations and because most modern processors execute things out-of-order. Crashing, unlike throwing, eliminates a dependency chain which means that the processor can execute more instructions at the same time. It would be nice if somebody with more technical knowledge than me could confirm this, though.)
Changing the behavior of Array accesses is a commonly rejected proposal. You may want to read the reasoning for this by clicking on this link.
Regarding the comment by Chris Lattner you mentioned, I’m almost certain that he wasn’t referring to the proposal itself. It seems that he was actually referring to this comment by David Waite which proposes a way to recover from crashes in a distributed concurrency model (I believe like erlang or like this proposal). The PDF he links to doesn’t talk about “optional throwing” at all, but it does mention actors in distributed compute models and terminating a crashing actor instead of the entire program at the very bottom.