1
+ use crate :: cell:: UnsafeCell ;
1
2
use crate :: marker:: { PointerLike , Unpin } ;
2
3
use crate :: ops:: { CoerceUnsized , DispatchFromDyn } ;
3
4
use crate :: pin:: Pin ;
4
5
use crate :: { fmt, ptr} ;
5
6
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;
7
8
/// 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.
8
11
///
9
12
/// However, even if you define your type like `pub struct Wrapper(UnsafePinned<...>)`, it is still
10
13
/// very risky to have an `&mut Wrapper` that aliases anything else. Many functions that work
@@ -17,38 +20,24 @@ use crate::{fmt, ptr};
17
20
/// the public API of a library. It is an internal implementation detail of libraries that need to
18
21
/// support aliasing mutable references.
19
22
///
20
- /// Further note that this does *not* lift the requirement that shared references must be read-only!
21
- /// Use `UnsafeCell` for that.
22
- ///
23
23
/// This type blocks niches the same way `UnsafeCell` does.
24
24
#[ lang = "unsafe_pinned" ]
25
25
#[ repr( transparent) ]
26
26
#[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
27
27
pub struct UnsafePinned < T : ?Sized > {
28
- value : T ,
28
+ value : UnsafeCell < T > ,
29
29
}
30
30
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
+
31
35
/// When this type is used, that almost certainly means safe APIs need to use pinning to avoid the
32
36
/// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt
33
37
/// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned.
34
38
#[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
35
39
impl < T : ?Sized > !Unpin for UnsafePinned < T > { }
36
40
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
-
52
41
// `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since
53
42
// we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes
54
43
// unergonomic. A type that needs to be `!Send`/`!Sync` should really have an explicit
@@ -63,7 +52,7 @@ impl<T> UnsafePinned<T> {
63
52
#[ must_use]
64
53
#[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
65
54
pub const fn new ( value : T ) -> Self {
66
- UnsafePinned { value }
55
+ UnsafePinned { value : UnsafeCell :: new ( value ) }
67
56
}
68
57
69
58
/// Unwraps the value, consuming this `UnsafePinned`.
@@ -72,7 +61,7 @@ impl<T> UnsafePinned<T> {
72
61
#[ unstable( feature = "unsafe_pinned" , issue = "125735" ) ]
73
62
#[ rustc_allow_const_fn_unstable( const_precise_live_drops) ]
74
63
pub const fn into_inner ( self ) -> T {
75
- self . value
64
+ self . value . into_inner ( )
76
65
}
77
66
}
78
67
0 commit comments