Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Jul 29, 2020

Conversation

matklad
Copy link
Member

@matklad matklad commented Jul 27, 2020

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
Collaborator

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
Copy link
Member Author

matklad commented Jul 27, 2020

cc tracking issue #74465

@kennytm
Copy link
Member

kennytm commented Jul 27, 2020

r? @KodrAus

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

KodrAus commented Jul 27, 2020

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
Copy link
Member Author

matklad commented Jul 27, 2020

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
Copy link
Contributor

bors commented Jul 28, 2020

☔ 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
Copy link
Member Author

matklad commented Jul 28, 2020

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
Copy link
Contributor

KodrAus commented Jul 28, 2020

Looks good to me!

@bors r+

@bors
Copy link
Contributor

bors commented Jul 28, 2020

📌 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