How to bound the method of trait to UnwindSafe

trait AA {
fn test(&self);
}

struct SS {}

impl AA for SS {
// Must be UnwindSafe
fn test(&self) {
}
}

I want all implementations of AA::test to be UnwindSafe. return compile error when the implementation is not unwind safe

UnwindSafe is a trait, and traits can only be implemented by types, not by functions (or methods).

UnwindSafe doesn't mean there will be no panic, it just marks the type to be safe across unwind boundary.

currently there's no language support to check a given function will not panic, but you can check GitHub - dtolnay/no-panic: Attribute macro to require that the compiler prove a function can't ever panic . it might not work for every use case, but should work for common usages.

TL;DR: I'm not sure exactly what you want to ensure, but UnwindSafe can't help you.


Functions items have their own types,[1] but those are always UnwindSafe since they contain no fields and UnwindSafe is structural. The trait is also poorly named since it doesn't convey anything unsafe code can rely on and is basically an invasive lint.

Note, however, that this is not an unsafe trait, so there is not a succinct contract that this trait is providing. Instead it is intended as more of a “speed bump” to alert users of catch_unwind that broken invariants may be witnessed and may need to be accounted for.

[...]

as mentioned above, the lack of unsafe means it is mostly an advisory. The AssertUnwindSafe wrapper struct can be used to force this trait to be implemented for any closed over variables passed to catch_unwind.

For example, it also doesn't detect the ability to cause invalid external state via &mut _ arguments, and you don't need unsafe to blindly wrap everything in AssertUnwindSafe either. So even if you impose the bound on some type implementors of your trait have to supply, it doesn't guarantee you anything -- if they fail the bound, they can just wrap things up in a newtype with an AssertUnwindSafe<_> field.

I think the main use it has is to tell others "I'm going to call catch_unwind on the generic closure you provide" as a favor.[2] But pretty much no-one does this and if you did, consumers may find it more annoying than helpful -- because consumers also can't assume you're not catching unwinds if you don't provide the bound anyway.[3]

(For these reasons it's not uncommon to consider the trait a failed experiment.)


  1. which e.g. implement Fn ↩︎

  2. or "favor" ↩︎

  3. You can also just wrap what they supply in AssertUnwindSafe without knowing anything about what it does... which is what the std test framework does for example. ↩︎

OOM appears as a panic in rust, and I am trying to capture and recover it with follow code.

catch_unwind(std::panic::AssertUnwindSafe(f)) {
        Ok(res) => Ok(res),
        Err(cause) => match cause.downcast_ref::<&'static str>() {
            None => match cause.downcast_ref::<String>() {
                None => Err(Error("Sorry, unknown panic message")),
                Some(message) => Err(Error(message.to_string())),
            },
            Some(message) => Err(Error(message.to_string())),
        },
    }

When I run it, it always encounters panicked at 'panic in a function that cannot unwind' and exits the process. So how can I ensure that my function is UnwindSafe?

It's an abort by default. I'm not aware of any way to prevent aborts or other non-unwinding termination calls in your code, if that's the goal. (You can't prevent abrupt termination generally as the OS might do it to you.)

Again, the trait doesn't mean much and it's structural property to boot (not a property of a function body). So I don't know how to respond to that. What are you trying to accomplish in English?

(Incidentally, your example can't quite compile and it seems odd to try and allocating a String when recovering from an allocation failure. )

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.