Because then you need to complicate the compiler with a diagnostic against misuse, which has to work 100% right in all situations and be maintained forever.
Because Rust has a safety culture, and provides threading, it is crucial that that the compiler will reject types you cannot safely send to another thread. So it does.
So the "diagnostic against misuse" you're concerned about is a necessary part of the compiler anyway.
Indeed, although Rc has this line:
impl<T: ?Sized, A: Allocator> !Send for Rc<T, A> {}
(which means roughly "You can't send this type to another thread")
It also has these lines:
// Note that this negative impl isn't strictly necessary for correctness,
// as `Rc` transitively contains a `Cell`, which is itself `!Sync`.
It's not just Arc<T> vs. Rc<T> that's relevant for thread safety, though. Pretty much any kind of shared mutability requires extra protection (locks or atomicity) to work safely across threads, so there has to be some way to indicate whether or not that extra protection is present. Not to mention objects that interact with FFI, such as mutex locks, which must be unlocked from the same thread. It would be a huge performance drain to demand that "every value everywhere must be usable from every thread".
Comments
Why not have such a thing, when it is strictly more performant for any program that has data which isn't accessed concurrently?
Because then you need to complicate the compiler with a diagnostic against misuse, which has to work 100% right in all situations and be maintained forever.
Because Rust has a safety culture, and provides threading, it is crucial that that the compiler will reject types you cannot safely send to another thread. So it does.
So the "diagnostic against misuse" you're concerned about is a necessary part of the compiler anyway.
Indeed, although Rc has this line:
(which means roughly "You can't send this type to another thread")It also has these lines:
It's not just Arc<T> vs. Rc<T> that's relevant for thread safety, though. Pretty much any kind of shared mutability requires extra protection (locks or atomicity) to work safely across threads, so there has to be some way to indicate whether or not that extra protection is present. Not to mention objects that interact with FFI, such as mutex locks, which must be unlocked from the same thread. It would be a huge performance drain to demand that "every value everywhere must be usable from every thread".