Negative views on Rust: panicking

Moderator note: split from Negative views on Rust ( not mine! )

One big thing bugs me about rust, but I can't really think of a constructive way to discuss it. My problem is panics: they should not be baked so deeply into the language.

First of all, unwindable panics are exceptions, with all the costs that that entails. I strongly believe that the ability to catch any panic from any context was a design mistake. Look at how many aspects of the language are affected by panic handling; for definiteness I'll just mention mutex poisoning (which can only happen as a result of an unwound panic), but I'm constantly seeing apparently simple design proposals foundering on the need for panic handling.

I've no good ideas how this could have been done better. I wonder if an UnwindOnPanic trait might help: only functions with this trait can be unwound. Working out the details would be tricky ... and kind of futile this late in the day, I suspect.

Similarly, there's no good way to write panic free rust. In a similar vein perhaps there should be a Panic trait, only functions with this trait can generate panics, and most functions don't implement this.


Well, the std library mutex does track if a panic occurs while a mutex is locked. I don't see this as a problem ( I suspect it's rather rare to panic in a mutex-locked section of code ). I don't have any problem with the way panics work in Rust, at least not that I can think of right now!

Panic is remnant from early days when Rust was envisioned as much different language and there are lot of guys who want to, somehow, write panic-free code. Rust-in-linux guys struggle with with it, e.g..

Unfortunately that's the design which is remnant of a times from when Rust was envisioned as radically different language and it's not clear how to resolve that issue, today.

But, kudos: that one is, at least, sensible criticism. Everyone agrees that panic is misdesigned, the only question is how to fix that (and if you may even fix that without creating radically different, incompatible, language).


I don't! Please explain how it is mis-designed!

1 Like

Except if the codebase was using catch_unwind as a general purpose error handling strategy.

Panic violates don't pay for what you don't use principle.

It's not present at type level which means that you can not, practically speaking, introduce simple and useful #[no_panic] attribute. And because it shouldn't cross FFI boundaries you are forced to deal with it even if you don't need it.

There are hacky ways to avoid panic (like no-panics-whatsoever) but they use linker hacks which leads to cryptic error messages and hard-to-debug issues where innocent change in one crate may lead to problems in radically different crate.

Panic may also make it hard to support certain invariants (std library mutex does know about panics and so should all custom types you design).

So yeah, panic is serious problem for Rust (almost, but not quite as problematic as tracing GC in other languages), but it's not clear how much work would it be to wean Rust of panic (the only obvious fact is that this cost would be immense).


If panic always aborted, then a += b could just be syntax sugar for a = a + b. With nonaborting panics this doesn't work because *r = *r + 1 doesn't compile when r is a mutable reference to a non-Copy type. It doesn't compile because + might panic and then *r would be left with no value.


I agree that there are some problems with panics, but I don't think the += one is one of them.


Any specific reason why that is a bad idea? It seems redundant to have both Add and AddAssign as separate traits. I was implementing AddAssign using Add and had to put in a dummy value in the meantime. I could have used the take_mut crate instead. It's all unnecessary costs: both in terms of how many traits need to be implemented, then documented, and also i think there is a small runtime cost in both workarounds. The only reason I can think of why two traits are needed is panic unwinding.

I mean without it, this wouldn't compile:

fn increment(num: &mut BigInt) {
    *num += 1;

Exactly my point. It would compile if the language allowed you to move out and back in to a &mut reference. It doesn't allow it because there might be a panic in the meantime.

Ah, well, I agree that there are issues with panic. I don't agree it should be removed entirely.


It would be nice if panics could be controlled. In particular, I think rust needs two controls over panics:

  1. It should be possible to write code that can be guaranteed to never be unwound. In particular, this would (in retrospect) allow mutex poisoning to become an obsolete notion, and all the other cases (constantly popping up on IRL discussions) where panics need special and complex handling could be avoided.
  2. We need to be able to write panic free rust code.

No good ideas how to get there from here beyond my initial remarks.

Abstraction. I think the point is not thinking about those complex things and just think about what you want your program to do. The way I understand the concept, that is why there are "Higher" level languages. So the programmer does not have to think about gory details.

I think I would have liked Rust without panic. But it's moot point because it's intertwined with other Rust features so deeply that attempting to remove it would be entirely unrealistic.

It's probably possible to remove it after decades-long process, but I'm not even sure it's worth it.

Maybe we may want to have Rust 2.0 at some point and panic can be removed there, but I, for one, don't hold my breath: 10 or 20 years down the road when such thing may, realistically, be attempted, it would probably be better to just create an entirely new language rather than try to create Rust 2.0.


A post was merged into an existing topic: Negative views on Rust ( not mine! )

Panics are important for UX in gui apps (Rust is a general-purpose language after all). Adding a panic handler which shows a dialog of the error rather than just crashing the whole application because of abort, unhandled panic or plain UB (which unwinding helps in preventing).


How so? Why not just check for errors like one does for any other code?

Actually I don't understand this whole conversation. I only get panics when there is some error situation I have not handled in my code. Well, that tells me I should fix my code and handle.

Meanwhile, panics due to running out of stack or memory or whatever are seriously fatal and I'm happy for my program to die immediately.

Does anyone have a simple example of the "panic" problem in Rust they could show here?


Some code doesn't return errors. Overloaded operators for example don't return a Result. Some std functions/methods panic as well, Vec subscript indexing panics for example on out of bounds indexing. Many std::string::String methods panic. Sometimes you don't have control over the libs you're using and what they're doing internally. Gui apps also run without a console usually, so no stderr, and the user wouldn't know the cause of the error when the application crashes. With a dialog, they can at least report back the problematic logic.


I still don't follow.

As far as I am concerned if ones program panics because of an array/vec subscripting error that indicates one has a bug in ones code and it should be fixed. I am happy that a panic terminates my program when that happens and I almost immediately know what to fix.

I'm not sure but I'm guessing your other examples are in the same vain.

That is true. However it seems to me that if a crate I am using panics because of array subscript error, or any of you other examples, then that crate is buggy and the panic shows what needs to be fixed. Either I'm lucky and the crate maintainer fixes it, or I have to take responsibility for what I'm running and fix it myself.

99% of the code I write does not have a user interface, let alone a GUI. I certainly don't want my binaries trying to open dialog boxes when the crash. No, my cloud server and embedded systems just need to log an error and die.

Heck, even Javascript, which was designed to build GUI interface stuff, from the beginning does not open dialogs when it encounters some impossible situation the programmer has created. Errors go to the console.