rust-lang / nomicon

The Dark Arts of Advanced and Unsafe Rust Programming
https://doc.rust-lang.org/nomicon/
Apache License 2.0
1.82k stars 262 forks source link

8.2 "Send and Sync" appears to misdefine "Send" #453

Open sethp opened 4 months ago

sethp commented 4 months ago

In reading https://doc.rust-lang.org/nomicon/send-and-sync.html for a definition of Send, I noticed that:

  1. When initially presented, Send is defined in terms of itself:

    A type is Send if it is safe to send it to another thread.

    Which should maybe read something like "if it is safe to pass ownership from one thread to another" or "if it is safe for the same inhabitant of the type to be used in different threads at different times."

  2. Later in the chapter, Send appears to be confused for Sync:

    Finally, let's think about whether our Carton is Send and Sync. Something can safely be Send unless it shares mutable state with something else without enforcing exclusive access to it. Each Carton has a unique pointer, so we're good.

    The middle sentence describes what it means to be !Sync, I believe, rather than !Send. I'm also not convinced a unique pointer is sufficient to imply that a type is Send—consider that the referent may be in the thread's local storage, or on the stack.

As a suggestion, it's probably more useful to provide counter-examples (what makes a type !Send) than attempting a constructive proof here. There's an excellent post on the user forums that discusses what it means to be !Send + Sync: https://users.rust-lang.org/t/example-of-a-type-that-is-not-send/59835/3

It might be further worth breaking down what it means to be each of:

Finally, it might be worth addressing types that are temporarily !Sync near when they are sent across threads; I'm imagining a sample data race repaired by adding appropriate memory barriers or adjusting atomic ordering constraints. I believe such types to contain potentially correct & useful programs that the (current) Rust typing system does not have a way to accept: a topic that seems like a good fit for the 'nomicon.

See also:

92 —which I believe a fix to this issue would also address

307 —a quick fix in the same neighborhood (though to be honest I just skipped the initial sentence)

436 —section 10.1.2 muddies the waters further by appearing to use T: Send + Sync as a stand-in for T is "thread-safe" without being particularly explicit about the differences. It might be more clear to discuss what happens to Arc<T>'s Send-soundness when T: !Sync, and vice versa (e.g. why is Arc<T>: !Sync when T: !Send?).