Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c738dcc

Browse files
committed
Add bits_for helper for tagged pointers & fixup docs
1 parent d4be8ef commit c738dcc

File tree

2 files changed

+42
-16
lines changed

2 files changed

+42
-16
lines changed

compiler/rustc_data_structures/src/tagged_ptr.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,45 @@ mod drop;
2424
pub use copy::CopyTaggedPtr;
2525
pub 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
4247
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+
///
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

92105
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>();
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

108121
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>();
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

124137
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>();
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

140153
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>();
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

155168
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>();
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+
}

compiler/rustc_middle/src/ty/list.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::arena::Arena;
2+
use rustc_data_structures::tagged_ptr::bits_for;
23
use rustc_serialize::{Encodable, Encoder};
34
use std::alloc::Layout;
45
use std::cmp::Ordering;
@@ -199,7 +200,7 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
199200
unsafe impl<T: Sync> Sync for List<T> {}
200201

201202
unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
202-
const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
203+
const BITS: usize = bits_for::<usize>();
203204

204205
#[inline]
205206
fn into_usize(self) -> usize {

0 commit comments

Comments
 (0)