Skip to content

Commit 76a4035

Browse files
committed
make UnsafePinned derive Copy, Send, Sync
1 parent 1f31c7b commit 76a4035

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

text/0000-unsafe-aliased.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,20 @@ struct UnsafePinned<T: ?Sized> {
218218
/// to avoid the aliases from becoming invalidated. Therefore let's mark this as `!Unpin`.
219219
impl<T> !Unpin for UnsafePinned<T> {}
220220

221+
/// The type is `Copy` when `T` is to avoid people assuming that `Copy` implies there
222+
/// is no `UnsafePinned` anywhere. (This is an issue with `UnsafeCell`: people use `Copy` bounds
223+
/// to mean `Freeze`.) Given that there is no `unsafe impl Copy for ...`, this is also
224+
/// the option that leaves the user more choices (as they can always wrap this in a `!Copy` type).
225+
impl<T: Copy> Copy for UnsafePinned<T> {}
226+
impl<T: Copy> Clone for UnsafePinned<T> {
227+
fn clone(&self) -> Self { *self }
228+
}
229+
230+
// `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since
231+
// we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes
232+
// unergonomic. A type that needs to be `!Send`/`!Sync` should really have an explicit
233+
// opt-out itself, e.g. via an `PhantomData<*mut T>` or (one day) via `impl !Send`/`impl !Sync`.
234+
221235
impl<T: ?Sized> UnsafePinned<T> {
222236
/// Constructs a new instance of `UnsafePinned` which will wrap the specified
223237
/// value.
@@ -421,12 +435,7 @@ Adding something like this to Rust has been discussed many times throughout the
421435
Places in the standard library that use `impl !Unpin for` and the generator lowering are adjusted to use `UnsafePinned` instead.
422436
Then as long as nobody outside the standard library used the unstable `impl !Unpin for`, switching the `noalias`-opt-out to the `UnsafeUnpin` trait is actually backwards compatible with the (never explicitly supported) `Unpin` hack!
423437
- Relatedly, in which module should this type live?
424-
- Should this type `derive(Copy)`? `UnsafeCell` does not, which is unfortunate because it now means some people might use `T: Copy` as indication that there is no `UnsafeCell` in `T`.
425438
- `Unpin` [also affects the `dereferenceable` attribute](https://github.com/rust-lang/rust/pull/106180), so the same would happen for this type. Is that something we want to guarantee, or do we hope to get back `dereferenceable` when better semantics for it materialize on the LLVM side?
426-
- When should `UnsafePinned<T>` be `Send` or `Sync`?
427-
`UnsafeCell` is `Send` but not `Sync` because of its interaction with shared references.
428-
The corresponding choice for `UnsafePinned` would be to make it `Sync` but not `Send`, but that seems like an odd choice.
429-
Given that `SyncUnsafeCell` was eventually proposed because the `!Sync` bound on `UnsafeCell` turned out to be too safe of a default for some cases, it may make sense to do the same with `UnsafePinned` and just have it inherit both `Send` and `Sync`.
430439

431440
# Future possibilities
432441
[future-possibilities]: #future-possibilities

0 commit comments

Comments
 (0)