From 2b0797aef509e4e245128ff24277f72da23b133f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 May 2025 16:20:32 +0200 Subject: [PATCH] UnsafePinned: also include the effects of UnsafeCell --- library/core/src/pin/unsafe_pinned.rs | 33 +++++++++------------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs index f65e83662fef..dbcceb807aba 100644 --- a/library/core/src/pin/unsafe_pinned.rs +++ b/library/core/src/pin/unsafe_pinned.rs @@ -1,10 +1,13 @@ +use crate::cell::UnsafeCell; use crate::marker::{PointerLike, Unpin}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::Pin; use crate::{fmt, ptr}; -/// This type provides a way to opt-out of typical aliasing rules; +/// This type provides a way to entirely opt-out of typical aliasing rules; /// specifically, `&mut UnsafePinned` is not guaranteed to be a unique pointer. +/// This also subsumes the effects of `UnsafeCell`, i.e., `&UnsafePinned` may point to data +/// that is being mutated. /// /// However, even if you define your type like `pub struct Wrapper(UnsafePinned<...>)`, it is still /// very risky to have an `&mut Wrapper` that aliases anything else. Many functions that work @@ -17,38 +20,24 @@ use crate::{fmt, ptr}; /// the public API of a library. It is an internal implementation detail of libraries that need to /// support aliasing mutable references. /// -/// Further note that this does *not* lift the requirement that shared references must be read-only! -/// Use `UnsafeCell` for that. -/// /// This type blocks niches the same way `UnsafeCell` does. #[lang = "unsafe_pinned"] #[repr(transparent)] #[unstable(feature = "unsafe_pinned", issue = "125735")] pub struct UnsafePinned { - value: T, + value: UnsafeCell, } +// Override the manual `!Sync` in `UnsafeCell`. +#[unstable(feature = "unsafe_pinned", issue = "125735")] +unsafe impl Sync for UnsafePinned {} + /// When this type is used, that almost certainly means safe APIs need to use pinning to avoid the /// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt /// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned. #[unstable(feature = "unsafe_pinned", issue = "125735")] impl !Unpin for UnsafePinned {} -/// The type is `Copy` when `T` is to avoid people assuming that `Copy` implies there is no -/// `UnsafePinned` anywhere. (This is an issue with `UnsafeCell`: people use `Copy` bounds to mean -/// `Freeze`.) Given that there is no `unsafe impl Copy for ...`, this is also the option that -/// leaves the user more choices (as they can always wrap this in a `!Copy` type). -// FIXME(unsafe_pinned): this may be unsound or a footgun? -#[unstable(feature = "unsafe_pinned", issue = "125735")] -impl Copy for UnsafePinned {} - -#[unstable(feature = "unsafe_pinned", issue = "125735")] -impl Clone for UnsafePinned { - fn clone(&self) -> Self { - *self - } -} - // `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since // we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes // unergonomic. A type that needs to be `!Send`/`!Sync` should really have an explicit @@ -63,7 +52,7 @@ impl UnsafePinned { #[must_use] #[unstable(feature = "unsafe_pinned", issue = "125735")] pub const fn new(value: T) -> Self { - UnsafePinned { value } + UnsafePinned { value: UnsafeCell::new(value) } } /// Unwraps the value, consuming this `UnsafePinned`. @@ -72,7 +61,7 @@ impl UnsafePinned { #[unstable(feature = "unsafe_pinned", issue = "125735")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> T { - self.value + self.value.into_inner() } }