Skip to content

Commit 5b85baa

Browse files
committed
A few clarifications in response to comments on the RFC.
1 parent 4bf047a commit 5b85baa

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

text/0000-send-improvements.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ follows:
1717
* Add an `Own` trait that is basically `Send + 'static` for convenience:
1818

1919
```rust
20-
unsafe trait Own : Send + 'static { }
21-
unsafe impl<T:Send+'static> Own for T { }
20+
trait Own : Send + 'static { }
21+
impl<T:Send+'static> Own for T { }
2222
```
2323
* Evaluate each `Send` bound currently in `libstd` and either leave it as-is, add an
2424
explicit `'static` bound, or bound it with another lifetime parameter.
@@ -85,11 +85,11 @@ access the the original data is through the unique reference, so it is safe to s
8585
threads. Similarly, we allow `&T` where `T` is `Sync`, even if it is not `Send`, since by the definition of `Sync` `&T` is already known to be threadsafe.
8686

8787
Note that this definition of `Send` is identical to the old definition of `Send` when
88-
restricted to `'static` lifetimes in safe code. Since `'static mut` items are not accessible
89-
in safe code, and it is not possible to create a safe `'&'static mut` outside of such an item, we
88+
restricted to `'static` lifetimes in safe code. Since `static mut` items are not accessible
89+
in safe code, and it is not possible to create a safe `&'static mut` outside of such an item, we
9090
know that if `T: Send + 'static`, it either has only `&'static` references, or has no references at
91-
all. Since `'static` references can only be created in `'static` items in safe code, and
92-
all `'static` items are `Sync`, we know that any such references are `Sync`. Thus, our
91+
all. Since `'static` references can only be created in `static` items and literals in safe code, and
92+
all `static` items (and literals) are `Sync`, we know that any such references are `Sync`. Thus, our
9393
new rule that `T` must be `Sync` for `&'static T` to be `Send` does not actually
9494
remove `Send` from any existing types. And since `T` has no `&'static mut` references,
9595
unless any were created in unsafe code, we also know that our rule allowing `&'static mut T`
@@ -98,9 +98,9 @@ with the old behavior, provided that old interfaces are updated to require `'sta
9898
create unsafe `'static` and `'static mut` references. But unsafe types like these were already not
9999
guaranteed to be threadsafe by Rust's type system.
100100

101-
Another important note is that with this definition, `Send` will fulfill the proposed role of `Sync` in a fork-join concurrency library. At present, to use `Sync` in a fork-join library one must make the implicit assumption that if `T` is `Sync`, `T` is `Send`. One might be tempted to codify this by making `Sync` a subtype of `Send`. Unfortunately, this is not always the case, though it should be most of the time. A type can be created with `&mut` methods that are not thread safe, but no `&`-methods that are not thread safe. An example would be a version of `Rc` with a `clone_mut()` method that took `&mut self` and no other `clone()` method. It could be thread-safely shared provided that a `&mut` reference was not sent to another thread, since then it could only be cloned in its original thread and could not be dropped while shared (hence, it is `Sync`), but a mutable reference could not, nor could it be moved into another thread (hence, it is not `Send`). However, because `&T` is Send if `T` is Sync (per the new definition), adding a `Send` bound will guarantee that only shared pointers of this type are moved between threads.
101+
Another important note is that with this definition, `Send` will fulfill the proposed role of `Sync` in a fork-join concurrency library. At present, to use `Sync` in a fork-join library one must make the implicit assumption that if `T` is `Sync`, `T` is `Send`. One might be tempted to codify this by making `Sync` a subtype of `Send`. Unfortunately, this is not always the case, though it should be most of the time. A type can be created with `&mut` methods that are not thread safe, but no `&`-methods that are not thread safe. An example would be a version of `Rc` called `RcMut`. `RcMut` would have a `clone_mut()` method that took `&mut self` and no other `clone()` method. `RcMut` could be thread-safely shared provided that a `&mut RcMut` was not sent to another thread. As long as that invariant was upheld, `RcMut` could only be cloned in its original thread and could not be dropped while shared (hence, `RcMut` is `Sync`) but a mutable reference could not be thread-safely shared, nor could it be moved into another thread (hence, `&mut RcMut` is not `Send`, which means that `RcMut` is not `Send`). Because `&T` is Send if `T` is Sync (per the new definition), adding a `Send` bound will guarantee that only shared pointers of this type are moved between threads, so our new definition of `Send` preserves thread safety in the presence of such types.
102102

103-
Thirdly, we'd add an `Own` trait as specified above. This would be used mostly as a convenience in user code for the current cases where `Send` is being used as a proxy for `Send + 'static`. We would probably still want to use `Send + 'static` as an explicit bound in most cases, just in case a user implemented `Own` but not `Send`.
103+
Thirdly, we'd add an `Own` trait as specified above. This would be used mostly as a convenience in user and library code for the current cases where `Send` is being used as a proxy for `Send + 'static`.
104104

105105
Finally, we'd hunt through existing instances of `Send` in Rust libraries and replace them with
106106
sensible defaults. For example, the `spawn()` APIs should all have `'static` bounds,

0 commit comments

Comments
 (0)