Skip to content

impl Trait in return position is inconsistently RefUnwindSafe #65986

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

Closed
jakoschiko opened this issue Oct 30, 2019 · 2 comments
Closed

impl Trait in return position is inconsistently RefUnwindSafe #65986

jakoschiko opened this issue Oct 30, 2019 · 2 comments

Comments

@jakoschiko
Copy link
Contributor

The following code compiles:

fn foo() -> impl std::fmt::Debug {
    42
}

fn main() {
    let x = foo();
    let _ = std::panic::catch_unwind(|| println!("{:?}", x));
}

I would expect that changing the implementation of foo is not a breaking change. But the following code does not compile:

fn foo() -> impl std::fmt::Debug {
    std::rc::Rc::new(42)
}

fn main() {
    let x = foo();
    let _ = std::panic::catch_unwind(|| println!("{:?}", x));
}

The compiler says:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the type `std::cell::UnsafeCell<usize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
 --> src/main.rs:7:13
  |
7 |     let _ = std::panic::catch_unwind(|| println!("{:?}", x));
  |             ^^^^^^^^^^^^^^^^^^^^^^^^ `std::cell::UnsafeCell<usize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
  |
  = help: within `impl std::fmt::Debug`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<usize>`
  = note: required because it appears within the type `std::cell::Cell<usize>`
  = note: required because it appears within the type `std::rc::RcBox<i32>`
  = note: required because it appears within the type `*const std::rc::RcBox<i32>`
  = note: required because it appears within the type `std::ptr::NonNull<std::rc::RcBox<i32>>`
  = note: required because it appears within the type `std::rc::Rc<i32>`
  = note: required because it appears within the type `impl std::fmt::Debug`
  = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `&impl std::fmt::Debug`
  = note: required because it appears within the type `[closure@src/main.rs:7:38: 7:60 x:&impl std::fmt::Debug]`
  = note: required by `std::panic::catch_unwind`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: Could not compile `playground`.

Tested version: rustc 1.38.0 (625451e37 2019-09-23)

@jakoschiko
Copy link
Contributor Author

Related to #45924?

@hanna-kruppe
Copy link
Contributor

UnwindSafe and RefUnwindSafe are auto traits (like Send and Sync) and impl trait return types are defined to "leak" auto traits, i.e., code can rely on whether auto traits are implemented by the concrete underlying type even if the auto trait is not explicitly listed in the bounds. This has been (and probably still is) controversial, but the feature is working the way it's been decided it should work after a years-long design process. So I'm going to close this as "not a bug".

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

No branches or pull requests

2 participants