4 ms·
Agreed on this, but this is ignoring the much more subtle effect of unwinding: it introduces optimization barriers around every function that "might" throw. As
by Gankro 10y ago
Agreed on this, but this is ignoring the much more subtle effect of unwinding: it introduces optimization barriers around every function that "might" throw.
As a basic example:
x = 1
something_that_can_fail()
x = 2
With unwinding, the `x = 1` write must be preserved if whoever catches can observe it (and if that's unclear, it must be preserved conservatively).
The C++ STL riddled with complex machinery to try to work around this sort of thing because everything can throw. Copies, moves, you name it! Not even reallocating an array can be done with realloc unless non-throwingness can be proven.
If you try to make throwing "opt in" like Java, then you end up with nasty "throwingness polymorphism" problems and end up with constructs like Swift's "rethrows". By contrast, error propagation through normal values naturally composes because it's really easy to write code that generically handles return values.
- softc 10y agoGood point. Some responses: Function calls themselves can force something like "x = 1" if x is observable from the callee. In the case where "x = 1" is not observable from the catch block, then there is no effect. In cases where you would use "try!" in Rust, in the equivalent C++ cases the catch block wouldn't be able see local variables since it would be in a parent function call. I think LTO largely eliminates this issue altogether since function bodies are visible to the optimizer in that case.