Better error reporting for Sync and type that impl !Sync

2a60d64
Opened by Paul FLORENCE at 2024-12-21 05:01:44

It would make a lot more sense if when a type impl !Sync the compiler could report an other error than the error that comes from this impl block.

For example, take a look at this code :

use std::sync::mpsc::channel;
use std::thread;

struct Foo {}

impl Foo {
    fn do_something(&self) {
        println!("hello");
    }
}

fn main() {
    let (tx, rx) = channel::<Foo>();
    thread::spawn(move || rx.iter().map(|f| f.do_something()));
}

Which outputs :

17 |     thread::spawn(move || rx.iter().map(|f| f.do_something()));
   |     ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<Foo>` cannot be shared between threads safely
   |
   = help: the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Receiver<Foo>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `&std::sync::mpsc::Receiver<Foo>`
   = note: required because it appears within the type `std::sync::mpsc::Iter<'_, Foo>`
   = note: required because it appears within the type `std::iter::Map<std::sync::mpsc::Iter<'_, Foo>, [closure@src/main.rs:17:41: 17:61]>`
   = note: required by `std::thread::spawn`

It would be way better if it could just say that Receiver is explicitly not Sync.

I know that this a bad example because the error is actually due to the fact that the compiler does not move rx because we are returning a value from the call to map(), but it was the only one that I had...

  1. Triage: no change.

    Esteban Kuber at 2020-02-14 09:25:36

  2. Current output:

    error[E0277]: `std::sync::mpsc::Receiver<Foo>` cannot be shared between threads safely
       --> f80.rs:14:5
        |
    14  |     thread::spawn(move || rx.iter().map(|f| f.do_something()));
        |     ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<Foo>` cannot be shared between threads safely
        |
        = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<Foo>`
        = note: required for `&std::sync::mpsc::Receiver<Foo>` to implement `Send`
    note: required because it appears within the type `Iter<'_, Foo>`
       --> /home/gh-estebank/rust/library/std/src/sync/mpsc/mod.rs:225:12
        |
    225 | pub struct Iter<'a, T: 'a> {
        |            ^^^^
    note: required because it appears within the type `Map<Iter<'_, Foo>, {closure@f80.rs:14:41}>`
       --> /home/gh-estebank/rust/library/core/src/iter/adapters/map.rs:61:12
        |
    61  | pub struct Map<I, F> {
        |            ^^^
    note: required by a bound in `spawn`
       --> /home/gh-estebank/rust/library/std/src/thread/mod.rs:684:8
        |
    680 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
        |        ----- required by a bound in this function
    ...
    684 |     T: Send + 'static,
        |        ^^^^ required by this bound in `spawn`
    

    Esteban Kuber at 2023-10-20 20:12:45