4 ms·
> I'm curious, what did Rust developers think was wrong with exceptions? To be fair, Rust effectively does have exceptions, in the form of panics. They unwind
by MaulingMonkey 6y ago
> I'm curious, what did Rust developers think was wrong with exceptions?
To be fair, Rust effectively does have exceptions, in the form of panics. They unwind the stack, can have different types (although &str/String are the most common/supported), can be caught and rethrown if not configured to abort the entire process instead.
They are used for exceptional, fatalish errors (including admittedly less exceptional bugs from unconsidered edge cases), and not regular "normal" / "expected" day-to-day error handling.
https://doc.rust-lang.org/std/panic/fn.catch_unwind.html https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
https://doc.rust-lang.org/std/panic/fn.resume_unwind.html https://doc.rust-lang.org/std/panic/fn.resume_unwind.html
> I'm pretty happy with them in other languages, as they allow me to focus more on the "normal" path in my code.
This is the boon and curse of exceptions.
Consistently writing exception-safe code when you're focused more on the normal path can actually be quite hard, as evidenced by all the code I've debugged written by coworkers who've failed to do so. Reviewing said code to attempt to enforce exception safety is similarly hard. Rust's `?`s, by contrast, make early-outs relatively easy to spot and reason about via their syntax.
Aside from leaked memory, double frees, and other bugs and crashes caused by invalid object states from failing to consider the case where execution is interrupted mid-operation by an exception, there's also all the undefined behavior from exceptions unwinding across C ABI boundaries for callbacks and other purpouses. This is suprisingly common in gamedev.
The larger and more widely used the codebase, the more frequent and normal the "abnormal" path becomes, and the more serious the consequences of ignoring it. Nobody cares if a quick utility script or command line tool occasionally crashes if you can just rerun it, or have it quickly patched, and don't suffer data loss. Focusing on the normal path is probably the right choice there!
But at the other extreme, if you're about to release a game, a crash affecting 1% of players is still pissing off thousands of people, and not all handhelds have internet connectivity for post-release patching. This results in weeks-long QA processes to try and catch all the nasty stuff, because delaying the release and throwing a wrench into a million dollar marketing plan might be less expensive than shipping shit broken by something as mundane as an unexpected exception. Focusing on all the edge cases is often the right choice there.
And when focusing on all the edge cases, explicit return based error handling tends to be much easier to read and reason about than exception based code, IME - even in Rust where a lot of heavy lifting might be hidden behind the occasional stray "?" - letting me get back to focusing on the "normal" path of my next task quicker - and with more confidence that I considered the appropriate edge cases of the previous task exhaustively and successfully.