I unfortunately know very little about Rust, but is it possible to recover from panics in Rust?
Because the problem that I'm seeing in Swift code (which also has a "crash on logic errors" approach) is that bugs can bring your whole system down, which is especially bad on server-side apps with multiple threads. Yes, you can use supervisord and/or load balancers, but you still lose in-flight requests.
By contrast, in a language with a runtime like Java or Ruby, you can catch almost everything at the top level, so you could just have some logic that generates a "whoops something went wrong" response in case of a serious error.
The point here is resiliency. I agree that you want to catch bugs early, and you should immediately abort execution once bad things happen; I also fundamentally agree that you don't want to litter your code with error types or other constructs that are supposed to never actually be used. But faults do happen in practice, because we write buggy code, and in such a case, it's good if you can isolate the fault and recover at a higher level. Languages like Erlang take this idea to an extreme.
This is currently a real problem for us with Swift, so I was wondering whether Rust has a better solution here.
However, this comes with a critical caveat: unwinding can be disabled when compiling an application, which means one cannot guarantee that catch_unwind will actually work. (If unwinding is disabled, then panics turn into unrecoverable aborts.)
For this reason, and because the standard error handling mechanism is done through return values, panicking is not an acceptable way to do robust error handling in Rust. Recovering from panics is useful in niche scenarios, like keeping a web server running even if a request causes a panic or in tests for ensuring that all tests run even if one panics. Which basically matches your key concern here.
(To be clear, I think this is mostly orthogonal to my original comment in this thread. :-))
Yep, that sounds like kind of what I would need. :)
But in general, exception handling is hard. There is value in having locally-unrecoverable, but globally-recoverable faults, stuff like that is probably where languages like Erlang shine.
Because the problem that I'm seeing in Swift code (which also has a "crash on logic errors" approach) is that bugs can bring your whole system down, which is especially bad on server-side apps with multiple threads. Yes, you can use supervisord and/or load balancers, but you still lose in-flight requests.
By contrast, in a language with a runtime like Java or Ruby, you can catch almost everything at the top level, so you could just have some logic that generates a "whoops something went wrong" response in case of a serious error.
The point here is resiliency. I agree that you want to catch bugs early, and you should immediately abort execution once bad things happen; I also fundamentally agree that you don't want to litter your code with error types or other constructs that are supposed to never actually be used. But faults do happen in practice, because we write buggy code, and in such a case, it's good if you can isolate the fault and recover at a higher level. Languages like Erlang take this idea to an extreme.
This is currently a real problem for us with Swift, so I was wondering whether Rust has a better solution here.