15
15
16
16
use std:: mem:: { self , ManuallyDrop } ;
17
17
use std:: ops:: Deref ;
18
+ use std:: ptr:: NonNull ;
18
19
use std:: rc:: Rc ;
19
20
use std:: sync:: Arc ;
20
21
@@ -29,21 +30,24 @@ pub use drop::TaggedPtr;
29
30
///
30
31
/// # Safety
31
32
///
32
- /// The usize returned from `into_usize` must be a valid, dereferenceable,
33
- /// pointer to [`<Self as Deref>::Target`]. Note that pointers to
34
- /// [`Self::Target`] must be thin, even though [`Self::Target`] may not be
35
- /// `Sized`.
33
+ /// The pointer returned from [`into_ptr`] must be a [valid], pointer to
34
+ /// [`<Self as Deref>::Target`]. Note that pointers to [`Self::Target`] must be
35
+ /// thin, even though [`Self::Target`] may not be `Sized`.
36
36
///
37
- /// Note that the returned pointer from `into_usize` should be castable to `&mut
38
- /// <Self as Deref>::Target` if `Self: DerefMut`.
37
+ /// Note that if `Self` implements [`DerefMut`] the pointer returned from
38
+ /// [`into_ptr`] must be valid for writes (and thus calling [`NonNull::as_mut`]
39
+ /// on it must be safe).
39
40
///
40
- /// The BITS constant must be correct. At least `BITS` bits, least-significant,
41
- /// must be zero on all returned pointers from `into_usize` .
41
+ /// The ` BITS` constant must be correct. At least `BITS` bits, least-significant,
42
+ /// must be zero on all pointers returned from [`into_ptr`] .
42
43
///
43
44
/// For example, if the alignment of [`Self::Target`] is 2, then `BITS` should be 1.
44
45
///
46
+ /// [`into_ptr`]: Pointer::into_ptr
47
+ /// [valid]: std::ptr#safety
45
48
/// [`<Self as Deref>::Target`]: Deref::Target
46
49
/// [`Self::Target`]: Deref::Target
50
+ /// [`DerefMut`]: std::ops::DerefMut
47
51
pub unsafe trait Pointer : Deref {
48
52
/// Number of unused (always zero) **least significant bits** in this
49
53
/// pointer, usually related to the pointees alignment.
@@ -63,15 +67,15 @@ pub unsafe trait Pointer: Deref {
63
67
/// [`Self::Target`]: Deref::Target
64
68
const BITS : usize ;
65
69
66
- fn into_usize ( self ) -> usize ;
70
+ fn into_ptr ( self ) -> NonNull < Self :: Target > ;
67
71
68
72
/// # Safety
69
73
///
70
74
/// The passed `ptr` must be returned from `into_usize`.
71
75
///
72
76
/// This acts as `ptr::read` semantically, it should not be called more than
73
77
/// once on non-`Copy` `Pointer`s.
74
- unsafe fn from_usize ( ptr : usize ) -> Self ;
78
+ unsafe fn from_ptr ( ptr : NonNull < Self :: Target > ) -> Self ;
75
79
76
80
/// This provides a reference to the `Pointer` itself, rather than the
77
81
/// `Deref::Target`. It is used for cases where we want to call methods that
@@ -81,7 +85,7 @@ pub unsafe trait Pointer: Deref {
81
85
/// # Safety
82
86
///
83
87
/// The passed `ptr` must be returned from `into_usize`.
84
- unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : usize , f : F ) -> R ;
88
+ unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : NonNull < Self :: Target > , f : F ) -> R ;
85
89
}
86
90
87
91
/// This describes tags that the `TaggedPtr` struct can hold.
@@ -106,17 +110,18 @@ unsafe impl<T> Pointer for Box<T> {
106
110
const BITS : usize = bits_for :: < Self :: Target > ( ) ;
107
111
108
112
#[ inline]
109
- fn into_usize ( self ) -> usize {
110
- Box :: into_raw ( self ) as usize
113
+ fn into_ptr ( self ) -> NonNull < T > {
114
+ // Safety: pointers from `Box::into_raw` are valid & non-null
115
+ unsafe { NonNull :: new_unchecked ( Box :: into_raw ( self ) ) }
111
116
}
112
117
113
118
#[ inline]
114
- unsafe fn from_usize ( ptr : usize ) -> Self {
115
- Box :: from_raw ( ptr as * mut T )
119
+ unsafe fn from_ptr ( ptr : NonNull < T > ) -> Self {
120
+ Box :: from_raw ( ptr. as_ptr ( ) )
116
121
}
117
122
118
- unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : usize , f : F ) -> R {
119
- let raw = ManuallyDrop :: new ( Self :: from_usize ( ptr) ) ;
123
+ unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : NonNull < T > , f : F ) -> R {
124
+ let raw = ManuallyDrop :: new ( Self :: from_ptr ( ptr) ) ;
120
125
f ( & raw )
121
126
}
122
127
}
@@ -125,17 +130,17 @@ unsafe impl<T> Pointer for Rc<T> {
125
130
const BITS : usize = bits_for :: < Self :: Target > ( ) ;
126
131
127
132
#[ inline]
128
- fn into_usize ( self ) -> usize {
129
- Rc :: into_raw ( self ) as usize
133
+ fn into_ptr ( self ) -> NonNull < T > {
134
+ unsafe { NonNull :: new_unchecked ( Rc :: into_raw ( self ) . cast_mut ( ) ) }
130
135
}
131
136
132
137
#[ inline]
133
- unsafe fn from_usize ( ptr : usize ) -> Self {
134
- Rc :: from_raw ( ptr as * const T )
138
+ unsafe fn from_ptr ( ptr : NonNull < T > ) -> Self {
139
+ Rc :: from_raw ( ptr. as_ptr ( ) )
135
140
}
136
141
137
- unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : usize , f : F ) -> R {
138
- let raw = ManuallyDrop :: new ( Self :: from_usize ( ptr) ) ;
142
+ unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : NonNull < T > , f : F ) -> R {
143
+ let raw = ManuallyDrop :: new ( Self :: from_ptr ( ptr) ) ;
139
144
f ( & raw )
140
145
}
141
146
}
@@ -144,17 +149,17 @@ unsafe impl<T> Pointer for Arc<T> {
144
149
const BITS : usize = bits_for :: < Self :: Target > ( ) ;
145
150
146
151
#[ inline]
147
- fn into_usize ( self ) -> usize {
148
- Arc :: into_raw ( self ) as usize
152
+ fn into_ptr ( self ) -> NonNull < T > {
153
+ unsafe { NonNull :: new_unchecked ( Arc :: into_raw ( self ) . cast_mut ( ) ) }
149
154
}
150
155
151
156
#[ inline]
152
- unsafe fn from_usize ( ptr : usize ) -> Self {
153
- Arc :: from_raw ( ptr as * const T )
157
+ unsafe fn from_ptr ( ptr : NonNull < T > ) -> Self {
158
+ Arc :: from_raw ( ptr. as_ptr ( ) )
154
159
}
155
160
156
- unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : usize , f : F ) -> R {
157
- let raw = ManuallyDrop :: new ( Self :: from_usize ( ptr) ) ;
161
+ unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : NonNull < T > , f : F ) -> R {
162
+ let raw = ManuallyDrop :: new ( Self :: from_ptr ( ptr) ) ;
158
163
f ( & raw )
159
164
}
160
165
}
@@ -163,32 +168,35 @@ unsafe impl<'a, T: 'a> Pointer for &'a T {
163
168
const BITS : usize = bits_for :: < Self :: Target > ( ) ;
164
169
165
170
#[ inline]
166
- fn into_usize ( self ) -> usize {
167
- self as * const T as usize
171
+ fn into_ptr ( self ) -> NonNull < T > {
172
+ NonNull :: from ( self )
168
173
}
169
174
170
175
#[ inline]
171
- unsafe fn from_usize ( ptr : usize ) -> Self {
172
- & * ( ptr as * const T )
176
+ unsafe fn from_ptr ( ptr : NonNull < T > ) -> Self {
177
+ ptr. as_ref ( )
173
178
}
174
179
175
- unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : usize , f : F ) -> R {
176
- f ( & * ( & ptr as * const usize as * const Self ) )
180
+ unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : NonNull < T > , f : F ) -> R {
181
+ f ( & ptr. as_ref ( ) )
177
182
}
178
183
}
179
184
180
185
unsafe impl < ' a , T : ' a > Pointer for & ' a mut T {
181
186
const BITS : usize = bits_for :: < Self :: Target > ( ) ;
187
+
182
188
#[ inline]
183
- fn into_usize ( self ) -> usize {
184
- self as * mut T as usize
189
+ fn into_ptr ( self ) -> NonNull < T > {
190
+ NonNull :: from ( self )
185
191
}
192
+
186
193
#[ inline]
187
- unsafe fn from_usize ( ptr : usize ) -> Self {
188
- & mut * ( ptr as * mut T )
194
+ unsafe fn from_ptr ( mut ptr : NonNull < T > ) -> Self {
195
+ ptr. as_mut ( )
189
196
}
190
- unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( ptr : usize , f : F ) -> R {
191
- f ( & * ( & ptr as * const usize as * const Self ) )
197
+
198
+ unsafe fn with_ref < R , F : FnOnce ( & Self ) -> R > ( mut ptr : NonNull < T > , f : F ) -> R {
199
+ f ( & ptr. as_mut ( ) )
192
200
}
193
201
}
194
202
0 commit comments