Skip to content
This repository has been archived by the owner on Sep 12, 2024. It is now read-only.

no-panic as a language feature #49

Open
yaahc opened this issue Feb 10, 2022 · 5 comments
Open

no-panic as a language feature #49

yaahc opened this issue Feb 10, 2022 · 5 comments

Comments

@yaahc
Copy link
Member

yaahc commented Feb 10, 2022

A common request I see is for the ability to require that the compiler prove a function can't ever panic. There are already libraries / tools that provide functionality like this.

As I see it we need to answer the following questions:

  • What are the use cases of no-panic?
  • What are the use cases for which no-panic and rustig are insufficient? (or, How do we benefit by making this a language feature?)
    • ???

As well as resolve the following issues:

  • interaction with optimizations
    • Frequently the codepaths in question that people wish to assert don't panic do have panics present which are removed when the optimizer is able to prove that they're unnecessary. This severely limits how we can implement this feature, since we'd need to check if there are still panics very late in the compilation pipeline. no-panic handles this by using linker shenanigans to produce an error when panics are still compiled in. rustig handles this by analyzing the final generated binary. It's unclear which strategy we'd follow when implementing this as a language feature.
    • Existing implementations don't work at all when panics are set to abort instead of unwind
    • The existing implementations make it so you can no longer compile in debug mode, or that you must enable some optimizations in debug mode.
  • interaction with stability guarantees
    • By making compiler errors depend on optimizations we risk introducing significant stability hazards. Changing a function such that the compiler can no longer prove that it doesn't panic or even introducing a panic would break code that previously successfully asserted that said function does not panic. It may be that we could never make this feature available except on nightly since using it would also effectively be opting into treating existing non-breaking changes as breaking changes.

And here are some previous discussions related to this topic:

@yaahc
Copy link
Member Author

yaahc commented Mar 20, 2022

Related: rust-embedded/wg#551

@adsick
Copy link

adsick commented Oct 6, 2022

What are the use cases of no-panic

I guess the main reason of not having panic is avoiding crashes and ensuring every possible case is checked&handled correctly. Crashes are not funny especially in context like kernel or some critical infrastructure, e.g. embedded. Take for example emergency alert systems. And generally I would prefer software that never crashes. Sorry if that sounds too obvious but I found it missing from your list of use cases.

Or it was more like use cases of crate https://github.com/dtolnay/no-panic ?

@StyMaar
Copy link

StyMaar commented Dec 2, 2022

A reason why I'd like to have a way to mark functions (or blocks) as “cannot possibly panic” is that it would allow to relax some rules that are annoying (especially for beginners, contributing to the learning curve) but needed to ensure safe rust is panic-safe.

Consider the following:

struct MyStruct{
    foo: Foo,
    // other fields go there
}

// I want to temporarily take ownership of the `foo` field, 
// this isn't currently allowed because it's not panic safe
fn my_function(my_obj: &mut MyStruct){

    let f: Foo = my_obj.foo; // now my_obj is in an invalid state.
    let new_f : Foo = do_something_with_a_foo(f);

   my_obj.foo = new_f; // my_obj is valid again \o/

}

There are work-around this issues (from refactoring everything, to just using Option<Foo>, but if we could enforce that my_function cannot panic then this pattern could be legalized inside no-panic functions (and the error message could be clearer also than a “cannot move out of borrowed content”, because this error message is a lie: you can definitely move out of borrowed content with mem::replace…).

As a conclusion, I should mention that the meaning of “no panic” is a bit different depending on the use-case you're targeting:

  • if you just care about panic-safety and avoiding UB during panics (either in unsafe code or in the example above), then a function that can abort is “no-panic”.
  • but if you do care about reliability, and ensuring that you cannot have software-induced crash, then you don't want to allow abort-ing either.

@safinaskar
Copy link

@StyMaar , this is very similar to https://crates.io/crates/replace_with . replace_with will certainly benefit from some kind of compile time assert of no-panic

@Fi3
Copy link

Fi3 commented Jun 27, 2023

Hi, below a POC for checking if blocks are panic free using the rustc_* libraries.

https://users.rust-lang.org/t/poc-statically-check-if-paths-are-panic-free/95948

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants