Skip to content

Fix RefUnwindSafe & UnwinsSafe impls for lazy::SyncLazy#74814

Merged
bors merged 1 commit into
rust-lang:masterfrom
matklad:unwind-safe
Jul 29, 2020
Merged

Fix RefUnwindSafe & UnwinsSafe impls for lazy::SyncLazy#74814
bors merged 1 commit into
rust-lang:masterfrom
matklad:unwind-safe

Conversation

@matklad

@matklad matklad commented Jul 27, 2020

Copy link
Copy Markdown
Contributor

I think we should implement those unconditionally with respect to F.

The user code can't observe the closure in any way, and we poison lazy if the closure itself panics.

But I've never fully wrapped my head around UnwindSafe traits, so 🤷‍♂️

@matklad matklad added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jul 27, 2020
@rust-highfive

Copy link
Copy Markdown
Contributor

r? @kennytm

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 27, 2020
@matklad

matklad commented Jul 27, 2020

Copy link
Copy Markdown
Contributor Author

cc tracking issue #74465

@kennytm

kennytm commented Jul 27, 2020

Copy link
Copy Markdown
Member

r? @KodrAus

@rust-highfive rust-highfive assigned KodrAus and unassigned kennytm Jul 27, 2020
@KodrAus

KodrAus commented Jul 27, 2020

Copy link
Copy Markdown
Contributor

Hmm, I think we need the closure to be unwind safe, because users can observe panics through borrowed arguments. Right now, this won’t compile:

let not_unwind_safe = std::cell::RefCell::new(42);

let l = std::lazy::SyncLazy::new(|| {
    let mut a = not_unwind_safe.borrow_mut();
    *a = 43;
    
    panic!("lol");
    
    *a
});

std::panic::catch_unwind(|| {
    let a = *l;
});

But if we implement RefUnwindSafe unconditionally then it will, and we can observe the state of not_unwind_safe across the catch_unwind.

They’re pretty niche traits 🙂 I use this blanket impl to try remember how they interact:

impl<T: RefUnwindSafe + ?Sized> UnwindSafe for &T {} // and Rc<T> and Arc<T> etc

fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> { .. }

So UnwindSafe is the main trait for values that will still make sense if passed by value into a recoverable scope, and RefUnwindSafe is used to implement UnwindSafe for smart pointers and other types that are passed by value themselves but are logically borrowed.

Looking at them now, should the impl be:

impl<T: RefUnwindSafe, F: UnwindSafe> RefUnwindSafe for SyncLazy<T, F> {}

because we move out of F when initializing?

It might also be worth moving these impls into the std::panic module alongside the others.

@matklad

matklad commented Jul 27, 2020

Copy link
Copy Markdown
Contributor Author

Yup, I agree with your reasoning, I think this is rougthly the same justification we use for Send&Sync impls here. Pushed an update.

@bors

bors commented Jul 28, 2020

Copy link
Copy Markdown
Collaborator

☔ The latest upstream changes (presumably #73265) made this pull request unmergeable. Please resolve the merge conflicts.

The logic here is the same as for Send&Sync impls.
@matklad

matklad commented Jul 28, 2020

Copy link
Copy Markdown
Contributor Author

Rebased onto master. I decided not to move stuff over to std::panic for now, so that we ca easier rename types, if we decide to.

@KodrAus

KodrAus commented Jul 28, 2020

Copy link
Copy Markdown
Contributor

Looks good to me!

@bors r+

@bors

bors commented Jul 28, 2020

Copy link
Copy Markdown
Collaborator

📌 Commit ed1439c has been approved by KodrAus

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 28, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 29, 2020
Rollup of 8 pull requests

Successful merges:

 - rust-lang#74266 (Clean up E0720 explanation)
 - rust-lang#74671 (add const generics array coercion test)
 - rust-lang#74707 (Add str::[r]split_once)
 - rust-lang#74814 (Fix RefUnwindSafe & UnwinsSafe impls for lazy::SyncLazy)
 - rust-lang#74859 (Update outdated readme)
 - rust-lang#74864 (ayu theme: Change doccomment color to `#a1ac88`)
 - rust-lang#74872 (Enable to ping RISC-V group via triagebot)
 - rust-lang#74891 (handle ConstEquate in rustdoc)

Failed merges:

r? @ghost
@bors bors merged commit bd91877 into rust-lang:master Jul 29, 2020
@KodrAus KodrAus mentioned this pull request Jul 29, 2020
9 tasks
@cuviper cuviper added this to the 1.47.0 milestone May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants