Skip to content

Commit de44732

Browse files
committed
auto merge of #13070 : huonw/rust/share-doc, r=alexcrichton
std: expand the `Share` docs to make them more precise. And give some examples about exactly what's `Share` and what's not.
2 parents 1f5571a + e9475b5 commit de44732

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

src/libstd/kinds.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,51 @@ pub trait Pod {
4040
// Empty.
4141
}
4242

43-
/// Types that can be safely shared between threads, hence thread-safe.
43+
/// Types that can be safely shared between tasks when aliased.
44+
///
45+
/// The precise definition is: a type `T` is `Share` if `&T` is
46+
/// thread-safe. In other words, there is no possibility of data races
47+
/// when passing `&T` references between tasks.
48+
///
49+
/// As one would expect, primitive types like `u8` and `f64` are all
50+
/// `Share`, and so are simple aggregate types containing them (like
51+
/// tuples, structs and enums). More instances of basic `Share` types
52+
/// include "immutable" types like `&T` and those with simple
53+
/// inherited mutability, such as `~T`, `Vec<T>` and most other
54+
/// collection types. (Generic parameters need to be `Share` for their
55+
/// container to be `Share`.)
56+
///
57+
/// A somewhat surprising consequence of the definition is `&mut T` is
58+
/// `Share` (if `T` is `Share`) even though it seems that it might
59+
/// provide unsynchronised mutation. The trick is a mutable reference
60+
/// stored in an aliasable reference (that is, `& &mut T`) becomes
61+
/// read-only, as if it were a `& &T`, hence there is no risk of a data
62+
/// race.
63+
///
64+
/// Types that are not `Share` are those that have "interior
65+
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
66+
/// in `std::cell`. These types allow for mutation of their contents
67+
/// even when in an immutable, aliasable slot, e.g. the contents of
68+
/// `&Cell<T>` can be `.set`, and do not ensure data races are
69+
/// impossible, hence they cannot be `Share`. A higher level example
70+
/// of a non-`Share` type is the reference counted pointer
71+
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
72+
/// reference, which modifies the reference counts in a non-atomic
73+
/// way.
74+
///
75+
/// For cases when one does need thread-safe interior mutability,
76+
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
77+
/// the `sync` crate do ensure that any mutation cannot cause data
78+
/// races. Hence these types are `Share`.
79+
///
80+
/// Users writing their own types with interior mutability (or anything
81+
/// else that is not thread-safe) should use the `NoShare` marker type
82+
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
83+
/// consider the user-defined type to be `Share`. Any types with
84+
/// interior mutability must also use the `std::ty::Unsafe` wrapper
85+
/// around the value(s) which can be mutated when behind a `&`
86+
/// reference; not doing this is undefined behaviour (for example,
87+
/// `transmute`-ing from `&T` to `&mut T` is illegal).
4488
#[lang="share"]
4589
pub trait Share {
4690
// Empty

0 commit comments

Comments
 (0)