@@ -24,32 +24,45 @@ mod drop;
24
24
pub use copy:: CopyTaggedPtr ;
25
25
pub use drop:: TaggedPtr ;
26
26
27
- /// This describes the pointer type encapsulated by TaggedPtr.
27
+ /// This describes the pointer type encapsulated by [`TaggedPtr`] and
28
+ /// [`CopyTaggedPtr`].
28
29
///
29
30
/// # Safety
30
31
///
31
32
/// The usize returned from `into_usize` must be a valid, dereferenceable,
32
- /// pointer to `<Self as Deref>::Target`. Note that pointers to `Pointee` must
33
- /// be thin, even though `Pointee` may not be sized.
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`.
34
36
///
35
37
/// Note that the returned pointer from `into_usize` should be castable to `&mut
36
- /// <Self as Deref>::Target` if `Pointer : DerefMut`.
38
+ /// <Self as Deref>::Target` if `Self : DerefMut`.
37
39
///
38
40
/// The BITS constant must be correct. At least `BITS` bits, least-significant,
39
41
/// must be zero on all returned pointers from `into_usize`.
40
42
///
41
- /// For example, if the alignment of `Pointee` is 2, then `BITS` should be 1.
43
+ /// For example, if the alignment of [`Self::Target`] is 2, then `BITS` should be 1.
44
+ ///
45
+ /// [`<Self as Deref>::Target`]: Deref::Target
46
+ /// [`Self::Target`]: Deref::Target
42
47
pub unsafe trait Pointer : Deref {
48
+ /// Number of unused (always zero) **least significant bits** in this
49
+ /// pointer, usually related to the pointees alignment.
50
+ ///
43
51
/// Most likely the value you want to use here is the following, unless
44
- /// your Pointee type is unsized (e.g., `ty::List<T>` in rustc) in which
45
- /// case you'll need to manually figure out what the right type to pass to
46
- /// align_of is.
52
+ /// your [`Self::Target`] type is unsized (e.g., `ty::List<T>` in rustc)
53
+ /// or your pointer is over/under aligned, in which case you'll need to
54
+ /// manually figure out what the right type to pass to [`bits_for`] is, or
55
+ /// what the value to set here.
47
56
///
48
- /// ```ignore UNSOLVED (what to do about the Self)
57
+ /// ```rust
49
58
/// # use std::ops::Deref;
50
- /// std::mem::align_of::<<Self as Deref>::Target>().trailing_zeros() as usize;
59
+ /// # type Self = &'static u64;
60
+ /// bits_for::<Self::Target>()
51
61
/// ```
62
+ ///
63
+ /// [`Self::Target`]: Deref::Target
52
64
const BITS : usize ;
65
+
53
66
fn into_usize ( self ) -> usize ;
54
67
55
68
/// # Safety
@@ -90,7 +103,7 @@ pub unsafe trait Tag: Copy {
90
103
}
91
104
92
105
unsafe impl < T > Pointer for Box < T > {
93
- const BITS : usize = std :: mem :: align_of :: < T > ( ) . trailing_zeros ( ) as usize ;
106
+ const BITS : usize = bits_for :: < Self :: Target > ( ) ;
94
107
#[ inline]
95
108
fn into_usize ( self ) -> usize {
96
109
Box :: into_raw ( self ) as usize
@@ -106,7 +119,7 @@ unsafe impl<T> Pointer for Box<T> {
106
119
}
107
120
108
121
unsafe impl < T > Pointer for Rc < T > {
109
- const BITS : usize = std :: mem :: align_of :: < T > ( ) . trailing_zeros ( ) as usize ;
122
+ const BITS : usize = bits_for :: < Self :: Target > ( ) ;
110
123
#[ inline]
111
124
fn into_usize ( self ) -> usize {
112
125
Rc :: into_raw ( self ) as usize
@@ -122,7 +135,7 @@ unsafe impl<T> Pointer for Rc<T> {
122
135
}
123
136
124
137
unsafe impl < T > Pointer for Arc < T > {
125
- const BITS : usize = std :: mem :: align_of :: < T > ( ) . trailing_zeros ( ) as usize ;
138
+ const BITS : usize = bits_for :: < Self :: Target > ( ) ;
126
139
#[ inline]
127
140
fn into_usize ( self ) -> usize {
128
141
Arc :: into_raw ( self ) as usize
@@ -138,7 +151,7 @@ unsafe impl<T> Pointer for Arc<T> {
138
151
}
139
152
140
153
unsafe impl < ' a , T : ' a > Pointer for & ' a T {
141
- const BITS : usize = std :: mem :: align_of :: < T > ( ) . trailing_zeros ( ) as usize ;
154
+ const BITS : usize = bits_for :: < Self :: Target > ( ) ;
142
155
#[ inline]
143
156
fn into_usize ( self ) -> usize {
144
157
self as * const T as usize
@@ -153,7 +166,7 @@ unsafe impl<'a, T: 'a> Pointer for &'a T {
153
166
}
154
167
155
168
unsafe impl < ' a , T : ' a > Pointer for & ' a mut T {
156
- const BITS : usize = std :: mem :: align_of :: < T > ( ) . trailing_zeros ( ) as usize ;
169
+ const BITS : usize = bits_for :: < Self :: Target > ( ) ;
157
170
#[ inline]
158
171
fn into_usize ( self ) -> usize {
159
172
self as * mut T as usize
@@ -166,3 +179,15 @@ unsafe impl<'a, T: 'a> Pointer for &'a mut T {
166
179
f ( & * ( & ptr as * const usize as * const Self ) )
167
180
}
168
181
}
182
+
183
+ /// Returns the number of bits available for use for tags in a pointer to `T`
184
+ /// (this is based on `T`'s alignment).
185
+ pub const fn bits_for < T > ( ) -> usize {
186
+ let bits = std:: mem:: align_of :: < T > ( ) . trailing_zeros ( ) ;
187
+
188
+ // This is a replacement for `.try_into().unwrap()` unavailable in `const`
189
+ // (it's fine to make an assert here, since this is only called in compile time)
190
+ assert ! ( ( bits as u128 ) < usize :: MAX as u128 ) ;
191
+
192
+ bits as usize
193
+ }
0 commit comments