@@ -24,32 +24,45 @@ mod drop;
2424pub use copy:: CopyTaggedPtr ;
2525pub use drop:: TaggedPtr ;
2626
27- /// This describes the pointer type encapsulated by TaggedPtr.
27+ /// This describes the pointer type encapsulated by [`TaggedPtr`] and
28+ /// [`CopyTaggedPtr`].
2829///
2930/// # Safety
3031///
3132/// 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`.
3436///
3537/// 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`.
3739///
3840/// The BITS constant must be correct. At least `BITS` bits, least-significant,
3941/// must be zero on all returned pointers from `into_usize`.
4042///
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
4247pub unsafe trait Pointer : Deref {
48+ /// Number of unused (always zero) **least significant bits** in this
49+ /// pointer, usually related to the pointees alignment.
50+ ///
4351 /// 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.
4756 ///
48- /// ```ignore UNSOLVED (what to do about the Self)
57+ /// ```rust
4958 /// # 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>()
5161 /// ```
62+ ///
63+ /// [`Self::Target`]: Deref::Target
5264 const BITS : usize ;
65+
5366 fn into_usize ( self ) -> usize ;
5467
5568 /// # Safety
@@ -90,7 +103,7 @@ pub unsafe trait Tag: Copy {
90103}
91104
92105unsafe 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 > ( ) ;
94107 #[ inline]
95108 fn into_usize ( self ) -> usize {
96109 Box :: into_raw ( self ) as usize
@@ -106,7 +119,7 @@ unsafe impl<T> Pointer for Box<T> {
106119}
107120
108121unsafe 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 > ( ) ;
110123 #[ inline]
111124 fn into_usize ( self ) -> usize {
112125 Rc :: into_raw ( self ) as usize
@@ -122,7 +135,7 @@ unsafe impl<T> Pointer for Rc<T> {
122135}
123136
124137unsafe 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 > ( ) ;
126139 #[ inline]
127140 fn into_usize ( self ) -> usize {
128141 Arc :: into_raw ( self ) as usize
@@ -138,7 +151,7 @@ unsafe impl<T> Pointer for Arc<T> {
138151}
139152
140153unsafe 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 > ( ) ;
142155 #[ inline]
143156 fn into_usize ( self ) -> usize {
144157 self as * const T as usize
@@ -153,7 +166,7 @@ unsafe impl<'a, T: 'a> Pointer for &'a T {
153166}
154167
155168unsafe 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 > ( ) ;
157170 #[ inline]
158171 fn into_usize ( self ) -> usize {
159172 self as * mut T as usize
@@ -166,3 +179,15 @@ unsafe impl<'a, T: 'a> Pointer for &'a mut T {
166179 f ( & * ( & ptr as * const usize as * const Self ) )
167180 }
168181}
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