1+ use crate :: cell:: UnsafeCell ;
12use crate :: marker:: { PointerLike , Unpin } ;
23use crate :: ops:: { CoerceUnsized , DispatchFromDyn } ;
34use crate :: pin:: Pin ;
45use crate :: { fmt, ptr} ;
56
6- /// This type provides a way to opt-out of typical aliasing rules;
7+ /// This type provides a way to entirely opt-out of typical aliasing rules;
78/// specifically, `&mut UnsafePinned<T>` is not guaranteed to be a unique pointer.
9+ /// This also subsumes the effects of `UnsafeCell`, i.e., `&UnsafePinned<T>` may point to data
10+ /// that is being mutated.
811///
912/// However, even if you define your type like `pub struct Wrapper(UnsafePinned<...>)`, it is still
1013/// very risky to have an `&mut Wrapper` that aliases anything else. Many functions that work
@@ -17,38 +20,24 @@ use crate::{fmt, ptr};
1720/// the public API of a library. It is an internal implementation detail of libraries that need to
1821/// support aliasing mutable references.
1922///
20- /// Further note that this does *not* lift the requirement that shared references must be read-only!
21- /// Use `UnsafeCell` for that.
22- ///
2323/// This type blocks niches the same way `UnsafeCell` does.
2424#[ lang = "unsafe_pinned" ]
2525#[ repr( transparent) ]
2626#[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
2727pub struct UnsafePinned < T : ?Sized > {
28- value : T ,
28+ value : UnsafeCell < T > ,
2929}
3030
31+ // Override the manual `!Sync` in `UnsafeCell`.
32+ #[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
33+ unsafe impl < T : ?Sized + Sync > Sync for UnsafePinned < T > { }
34+
3135/// When this type is used, that almost certainly means safe APIs need to use pinning to avoid the
3236/// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt
3337/// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned.
3438#[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
3539impl < T : ?Sized > !Unpin for UnsafePinned < T > { }
3640
37- /// The type is `Copy` when `T` is to avoid people assuming that `Copy` implies there is no
38- /// `UnsafePinned` anywhere. (This is an issue with `UnsafeCell`: people use `Copy` bounds to mean
39- /// `Freeze`.) Given that there is no `unsafe impl Copy for ...`, this is also the option that
40- /// leaves the user more choices (as they can always wrap this in a `!Copy` type).
41- // FIXME(unsafe_pinned): this may be unsound or a footgun?
42- #[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
43- impl < T : Copy > Copy for UnsafePinned < T > { }
44-
45- #[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
46- impl < T : Copy > Clone for UnsafePinned < T > {
47- fn clone ( & self ) -> Self {
48- * self
49- }
50- }
51-
5241// `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since
5342// we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes
5443// unergonomic. A type that needs to be `!Send`/`!Sync` should really have an explicit
@@ -63,7 +52,7 @@ impl<T> UnsafePinned<T> {
6352 #[ must_use]
6453 #[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
6554 pub const fn new ( value : T ) -> Self {
66- UnsafePinned { value }
55+ UnsafePinned { value : UnsafeCell :: new ( value ) }
6756 }
6857
6958 /// Unwraps the value, consuming this `UnsafePinned`.
@@ -72,7 +61,7 @@ impl<T> UnsafePinned<T> {
7261 #[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
7362 #[ rustc_allow_const_fn_unstable( const_precise_live_drops) ]
7463 pub const fn into_inner ( self ) -> T {
75- self . value
64+ self . value . into_inner ( )
7665 }
7766}
7867
0 commit comments