Live data from Hacker News

No-Panic Rust: A Nice Technique for Systems Programming

blog.reverberate.org

51–60 of 143 posts

Re: No-Panic Rust: A Nice Technique for Systems Programming

#51

This seems to obviate a lot of Rust's advantages (like a good std library). I wonder what it would take to write a nopanic-std library? Panics really seem bad for composability. And relying on the optimzer here seems like a fragile approach. (And how is there no -nopanic compiler flag?)

What I would like to see is a reliable distinction of different types of panics. In the environments where software I write is typically run, panics due to heap allocation failure are generally acceptable and rarely an indication of fragility. (By the time a heap allocation failure occurs, the computer is probably already thrashing and needs to be rebooted.) On the other hand, other kinds of panics are a bad sign. For example, I would frown on any library that panics just because it can't reach the Internet.

In other environments, like embedded or safety-critical devices, I would need a guarantee that even heap allocation failure can not cause a panic.

Re: No-Panic Rust: A Nice Technique for Systems Programming

#52
post #31

Earlier quoted context omitted.

https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-... ``` [profile.release] panic = 'abort' ```

that just makes the panics unrecoverable. It doesn't statically guarantee no panics.

There is no-panic [1] to turn panics in a function into compile errors, or the older no-panics-whatsoever [2] to do the same for the entire binary

1: https://crates.io/crates/no-panic

2: https://crates.io/crates/no-panics-whatsoever

Re: No-Panic Rust: A Nice Technique for Systems Programming

#53
post #18

Earlier quoted context omitted.

At least sources of panic! are easily greppable. Cutting corners on error handling is usually pretty obvious

I don't think grepping for panics is practical, unless you are trying to depend on exclusively no-panic libraries. Even if you are no_std, core has tons of APIs like unwrap(), index slicing, etc. that can panic if you violate the preconditions. It's not practical to grep for all of them.

There is panic-analyzer [1] that searches for code that needlessly panics. You can also use the no-panic macro [2] to turn possible panics in a specific function (including main) into a compile error

1: https://crates.io/crates/panic-analyzer

2: https://crates.io/crates/no-panic

Re: No-Panic Rust: A Nice Technique for Systems Programming

#54
post #43

Does Rust have something like a deep-codemodding macro that could be used to un-panic-fy an entire function etc. automatically? Something like: Given a function, rewrite its signature to return a Result if it doesn't already, rewrite each non-Resulty return site to a Some(), add a ? to every function call, then recurse into each called function and do the same.

It has `catch_unwind` [1], but that still retains the panicking runtime, so not sufficient in the context of the post. [1] https://doc.rust-lang.org/std/panic/fn.catch_unwind.html

It's also not guaranteed to catch every panic - sometimes (notably if a destructor panics during unwinding) a panic can turn into a process-abort.

Re: No-Panic Rust: A Nice Technique for Systems Programming

#55
post #35

Earlier quoted context omitted.

Sometimes the program is in an invalid state. You don't want to keep running the program. Better to fail spectacularly and clearly then to fail silently and try to hobble along.

The thing with functional programming (specifically, immutable data,) is that as long as the invalid state is immutable, you can just back up to some previous caller, and they can figure out whether to deal with it or whether to reject up the its previous caller. This is why Result (or Maybe, or runExceptT, and so on in other languages) is a perfectly safe way of handling unexpected or invalid data. As long as you en…

Say a function has some return type Result. If our only error handling mechanism is Err(e) then were restricted to E representing the set of errors due to invalid arguments and state, and the set of errors due to the program itself being implemented incorrectly.

In a good software architecture (imo) panics and other hard failure mechanisms are there for splitting E into E1 and E2, where E1 is the set of errors that can happen due to the caller screwing up and E2 being the set of errors that the caller screwed up. The caller shouldn't have to reason about the callee possibly being incorrect!

Functional programming doesn't really come into the discussion here - oftentimes this crops up in imperative or object oriented code where function signatures are lossy because code relies on side effects or state that the type system can't/won't capture (for example, a database or file persisted somewhere). Thats where you'll drop an assert or panic - not as a routine part of error handling.

Re: No-Panic Rust: A Nice Technique for Systems Programming

#56

Earlier quoted context omitted.

I don't think grepping for panics is practical, unless you are trying to depend on exclusively no-panic libraries. Even if you are no_std, core has tons of APIs like unwrap(), index slicing, etc. that can panic if you violate the preconditions. It's not practical to grep for all of them.

There is panic-analyzer [1] that searches for code that needlessly panics. You can also use the no-panic macro [2] to turn possible panics in a specific function (including main) into a compile error 1: https://crates.io/crates/panic-analyzer 2: https://crates.io/crates/no-panic

Panic-analyzer looks like it is based on heuristics, searching for known-panicing APIs. I tried it on a workspace that uses io::stdout() and it did not flag this as potentially panicing.

No-panic looks nifty: it appears to be reliable, which is great. I wish there was an easy way to automatically apply this annotation to every single function in a given file or crate.

Re: No-Panic Rust: A Nice Technique for Systems Programming

#57
post #39

The approach at the end of declaring invariants to the compiler so the compiler can eliminate panics seems accidentally genius. You can now add the same invariants as panicking asserts at the end of each function, and the compiler will prove to you that your functions are upholding the invariants. And of course you can add more panicking asserts to show other claims to be true, all tested at compile time. You've basi…

This isn't quite the same, but it reminds me of something a bit less clever (and a lot less powerful) I came up with a little while back when writing some code to handle a binary format that used a lot of 32-bit integers that I needed to use for math on indexes in vectors. I was fairly confident that the code would never need to run on 16-bit platforms, but converting from a 32-bit integer to a usize in Rust technica…

What about just doing something like

  #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
  #[inline(always)]
  const fn usize_to_u32(x: usize) -> u32 {
      x as u32
  }
and this way you can just call this function and you'll get a compile-time error (no such function) if you're on a 16-bit platform.

Re: No-Panic Rust: A Nice Technique for Systems Programming

#58
post #54

Earlier quoted context omitted.

It has `catch_unwind` [1], but that still retains the panicking runtime, so not sufficient in the context of the post. [1] https://doc.rust-lang.org/std/panic/fn.catch_unwind.html

It's also not guaranteed to catch every panic - sometimes (notably if a destructor panics during unwinding) a panic can turn into a process-abort.

To add to that, Rust code is generally not written to be 'exception-safe' when panics occur: if a third-party function causes a panic, or if your own code panics from within a callback, then memory may be leaked, and objects in use may end up in an incorrect or unusable state.

You really want to avoid sharing mutable objects across a catch_unwind() boundary, and also avoid using it on a regular basis. Aside from memory leaks, panicking runs the thread's panic hook, which by default prints a stacktrace. You can override the panic hook to be a no-op, but then you won't see anything for actual panics.

Re: No-Panic Rust: A Nice Technique for Systems Programming

#59
post #29

> Protocol Buffers Instead of serializing data (to disk, not the network), it would be much faster if Rust allowed us to allocate datastructures directly in an mmapped file, and allowed us to read back the data (basically patching the pointers so they become valid if the base address changed).

This is basically what Cap'n Proto does, and it uses offsets instead of pointers so that way the mmapped data can be used as-is.

Re: No-Panic Rust: A Nice Technique for Systems Programming

#60

Earlier quoted context omitted.

Same, the web view in my Android client crashed after a couple seconds.

I wonder if it's all the Godbolt iframes. Do you have the same problem on other pages, like https://blog.reverberate.org/2025/01/27/an-ode-to-header-fil... ?

Yeah, I think it's all those iframes. I'm seeing something weird on my Linux desktop - all the godbolt iframes crash on reload unless I have another tab with godbolt open. I didn't see anything obvious in Chrome's log.

I can't replicate the crash at all on my Linux cloud VM though. Usually the only difference there is that advertisers tend to not buy ads for clients on cloud IPs.

Post reply on HN