Live data from Hacker News

No-Panic Rust: A Nice Technique for Systems Programming

blog.reverberate.org

41–50 of 143 posts

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

#41
post #18
post #11

I've had an unpleasant amount of crashes with Rust software because people are way too quick to grab `panic!` as an out. This was most shocking to me in some of the Rust code Mozilla had integrated into Firefox (the CSS styling code). There was some font cache shenanigans that was causing their font loading to work only semi-consistently, and that would outright crash this subsystem, and tofu-ify CJK text entirely as…

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.

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

#42

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?)

Rust doesn't want to add any proof-system that isn't 100% repeatable, reliable, and forwards compatible to the language. The borrow checker is ok, because it meets those requirements. The optimizer based "no panic" proof system is not. It will break between releases as LLVM optimizations change, and there's no way to avoid it.

Trying to enforce no-panics without a proof system helping out is just not a very practical approach to programming. Consider code like

    some_queue.push_back("new_value");
    process(some_queue.pop_front().unwrap());
This code is obviously correct. It never panics. There's no better way to write it. The optimizer will instantly see that and remove the panicing branch. The language itself doesn't want to be in the business of trying to see things like that.

Or consider code like

    let mut count: usize = 0;
    for item in some_vec {
        // Do some stuff with item
        if some_cond() {
            count += 1;
        }
    }
This code never panics. Integer arithmetic contains a hidden panic path on overflow, but that can't occur here because the length of a vector is always less than usize::MAX.

Or so on.

Basically every practical language has some form of "this should never happen" root. Rust's is panics. C's is undefined behavior. Java's is exceptions.

Finally consider that this same mechanism is used for things like stack overflows, which can't be statically guaranteed to not occur short of rejecting recursion and knowledge of the runtime environment that rustc does not have.

---

Proof systems on top of rust like creusot or kani do tend to try to prove the absence of panics, because they don't have the same compunctions about not approving code today that they aren't absolutely sure they will approve tomorrow as well.

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

#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.

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

#44

Earlier quoted context omitted.

I’m seeing the same problem, the page crashes on Safari on iOS, saying a problem repeatedly occurred. Haven’t seen a webpage do that in quite a while.

Yep, same experience, same platform. I guess straight to reader mode, it is. EDIT - shockingly, reader mode also fails completely after the page reloads itself

I'm seeing the same problem--the page crashes on mobile (Brave). On desktop it loads, but all of the code cells have a crashed page symbol in them.

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

#45
post #18

Earlier quoted context omitted.

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

I mean... rust modules aren't typically in your CWD, no? they're not in some node_modules that you can grep, but in a cargo folder with /all of the libraries you ever used/, not just the ones you have for this one project.

For what it's worth, eg vscode can jump to definition even when your code is in a different crate that's not in your repository.

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

#46
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

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

#47

Earlier quoted context omitted.

While I would love this to be true, I'm not sure that this design can statically prove anything. For an assert to fail, you would have to actually execute a code sequence that causes the invariant to be violated. I don't see how the compiler could prove at compile time that the invariants are upheld.

An assert is just a fancy `if condition { panic(message) }`. If the optimizer can show that condition is always false, the panic is declared as dead code and eliminated. The post uses that to get the compiler to remove all panics to reduce the binary size. But you can also just check if panic code was generated (or associated code linked in), and if it was then the optimizer wasn't able to show that your assert can't…

Ah, I see what you are saying. Yes, if the optimizer is able to eliminate the postcondition check, I agree that it would constitute a proof that the code upholds the invariant.

The big question is how much real-world code the optimizer would be capable of "solving" in this way.

I wonder if most algorithms would eventually be solvable if you keep breaking them down into smaller pieces. Or if some would have some step of irreducible complexity that the optimizer cannot figure out, now matter how much you break it down.

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

#48
post #11

I've had an unpleasant amount of crashes with Rust software because people are way too quick to grab `panic!` as an out. This was most shocking to me in some of the Rust code Mozilla had integrated into Firefox (the CSS styling code). There was some font cache shenanigans that was causing their font loading to work only semi-consistently, and that would outright crash this subsystem, and tofu-ify CJK text entirely as…

While sure, more things could be baked as results, most of the time when you see a panic that's not the case. It's a violation of the callee's invariants that the caller fucked up.

Essentially an error means that the caller failed in a way that's expected. A panic means the caller broke some contract that wasn't expressed in the arguments.

A good example of this is array indexing. If you're using it you're saying that the caller (whoever is indexing into the array) has already agreed not to access out of bounds. But we still have to double check if that's the case.

And if you were to say that hey, that implies that the checks and branches should just be elided - you can! But not in safe rust, because safe code can't invoke undefined behavior.

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

#49
post #27
post #5

Does anyone know if there's an obvious reason that adding a `no_panic` crate attribute wouldn't be feasible? It certainly seems like an "obvious" thing to add so I'm hesitant to take the obvious nerd snipe bait.

You could do it, but I would prefer guarantees on a per-call chain basis using a sanitizer. It should be quite easy to write.

I'm no rustc expert, but from what little I know it seems like disabling panics for a crate would be an obvious first step. You make a great point though. Turning that into a compiler assertion of "this function will never panic" would also be useful.

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

#50
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.

It presumably avoids the linked in 300Kb that was supposedly part of the motivation for doing this though?
Post reply on HN