5 ms·
Indeed, I've heard at least one Rust developer argue for exactly that. However, since exceptions are not part of the public function API, I think they have to
by Jweb_Guru 12y ago
Indeed, I've heard at least one Rust developer argue for exactly that.
However, since exceptions are not part of the public function API, I think they have to be carefully packaged to ensure that they are only used in cases where catching them makes no sense (that is, for violated invariants, not normal runtime errors). The biggest nontechnical problem with unchecked exceptions in other languages is that they escape the type system and make it impossible to reason about code by looking at function signatures. This makes them unsuitable as general-purpose error reporting mechanisms, even though table-based unwinding is faster in the common case than error propagation through return statements.
Java tried to solve this problem using checked exceptions, which are probably my favorite feature in the whole language, but sadly I appear to be pretty much alone in liking them. Besides the Java community's total rejection of the feature, it was always hampered by the many ways Java offers to subvert it: unchecked exceptions of various kinds, misfeatures like Thread.stop, a standard that allows exceptions to be thrown at literally almost any point in the presence of VM problems, etc.
Personally I generally agree with the article author--exceptions are useful for some projects, but most of the time the best solution is to abort. Not having to worry about exception safety makes writing unsafe code vastly simpler and doesn't force you to write code in ways that can cause missed optimizations. You also don't have to worry about corrupted shared state as you do with thread unwinding, since processes actually have isolated address spaces. You can take advantage of hardware traps on failure modes like division by zero, which are significantly cheaper than exceptions. And, of course, you get faster compile times and smaller binaries (though the latter is not a big deal most of the time). So my feeling is that that should be the default, with an option to opt into using checked exceptions for projects that need it (web servers, Servo).
My other concern with fully supporting C++ exceptions would thus be that I don't think it would be nearly as easy to switch between the abort method and try-catch as between abort and task failure. I can see the argument for it, though--you're already going to have different semantics with abort, and in some cases the performance benefits of landing pads compared to return result propagation and/or process restart are important enough to outweigh the disadvantages.
- cousin_it 12y agoHow is abort better for reasoning about the code?
- Jweb_Guru 12y agoWhen code aborts, you don't have to reason about it in calling code. When you decide to abort, you are not just suggesting that there might be a problem. You are asserting "nope, there is no reasonable way I can continue here." Which is exactly what task failure is supposed to be used for, incidentally (which is why it was renamed to panic!)--normal, expected error conditions that you can actually do something useful about should be handled through the type system, not propagated through code that might not even be aware of its existence. In the meantime, abort completely cleans up any in-process state--closing network pipes, deleting temporary files, deallocating mmaped memory, and so on. And what it can't clean up can't be relied on anyway, because programs can always be aborted unexpectedly in other ways. Whether it's the OOM killer, various Rust behavior that triggers abort (panicking during unwinding, for example), stack overflow, power loss, or just SIGKILL, a robust program can never rely on its destructors running anyway (and destructors failing to run is explicitly not part of Rust's definition of unsafe). So ultimately, the reason abort is easier to reason about is that except in a few special cases (like embedded, where you may have complete control of the hardware--but you likely don't want to be using task failure there), your program already has to be designed to expect an abort at literally any time. Aborting may not always be desired behavior, but it never introduces additional cognitive load, or creates unsafety where it didn't already exist, in the way that exceptions do.