Unwind safety of rc::Weak?

This is curious:

let x = Rc::new(());
let y = Rc::downgrade(&x);
let z = catch_unwind(move || {
  panic!();
  x
});
y.upgrade().unwrap(); // panics.

So arguably Rc shouldn't be UnwindSafe (but can still be RefUnwindSafe), because it can break logical invariants?

But at the same time, Weak... arguably should. Because Weak can't create a broken invariant. Yeah?

In reality Rc is UnwindSafe and we can't change that, but, just so we understand UnwindSafe semantics correctly, in an ideal world Rc would be RefUnwindSafe and Weak would be UnwindSafe+RefUnwindSafe, yes?

Ultimately, the idea of unwind safety is to keep users from witnessing broken invariants in their own types. In this case, the unwind safety of Rc depends only on its inner value. Rc<T> is only UnwindSafe when T is RefUnwindSafe, i.e., T contains no interior mutability that could leak the user's information out. Since the reference count of an Rc has no important semantics can be broken by panics, allowing that information to leak from a RefUnwindSafe closure isn't considered to break unwind safety.

1 Like

Hmm, it's kinda weird that rc::Weak isn't UnwindSafe but sync::Weak is, tbh.

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.