Misc 10 @jdonszelmann

use std::future::Future;

struct ThreadSafePtr<T>(pub *const T);
unsafe impl<T> Send for ThreadSafePtr<T> {}

fn requires_send(_f: impl Future + Send) {}

fn main() {
    let x = 10;
    let y = ThreadSafePtr(&raw const x);

    requires_send(async move {
        println!("{}", unsafe{*y.0})
    })
}
Solution
error[E0277]: `*const i32` cannot be sent between threads safely
  --> examples/misc_10.rs:12:19
   |
12 |       requires_send(async move {
   |       ------------- ^---------
   |       |             |
   |  _____|_____________within this `{async block@examples/misc_10.rs:12:19: 12:29}`
   | |     |
   | |     required by a bound introduced by this call
13 | |         println!("{}", unsafe{*y.0})
14 | |     })
   | |_____^ `*const i32` cannot be sent between threads safely
   |
   = help: within `{async block@examples/misc_10.rs:12:19: 12:29}`, the trait `Send` is not implemented for `*const i32`
note: required because it's used within this `async` block
  --> examples/misc_10.rs:12:19
   |
12 |     requires_send(async move {
   |                   ^^^^^^^^^^
note: required by a bound in `requires_send`
  --> examples/misc_10.rs:6:36
   |
6  | fn requires_send(_f: impl Future + Send) {}
   |                                    ^^^^ required by this bound in `requires_send`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `code` (example "misc_10") due to 1 previous error

Despite the closure being move, not the whole ThreadSafePtr is moved into the async block. Rust allows us to move different fields of a struct into different closures or async blocks. Since we only access y.0, it only moves that field, which is a *const T, which is not Send, which means this code doesn't compile.

A slightly comical way to fix it is like this:


use std::future::Future;

struct ThreadSafePtr<T>(pub *const T);
unsafe impl<T> Send for ThreadSafePtr<T> {}

fn requires_send(_f: impl Future + Send) {}

fn main() {
    let x = 10;
    let y = ThreadSafePtr(&raw const x);

    requires_send(async move {
        let y = y; // <-- ADD THIS
        println!("{}", unsafe{*y.0})
    })
}

Note, before edition 2021, this kind of splitting was not possible and y would be moved into the closure as a whole.