mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Lift Pointer
's requirement for the pointer to be thin
fat pointers rule!
This commit is contained in:
parent
26232f1ff5
commit
9051331dd7
31
compiler/rustc_data_structures/src/aligned.rs
Normal file
31
compiler/rustc_data_structures/src/aligned.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use std::mem;
|
||||
|
||||
/// Returns the ABI-required minimum alignment of a type in bytes.
|
||||
///
|
||||
/// This is equivalent to [`mem::align_of`], but also works for some unsized
|
||||
/// types (e.g. slices or rustc's `List`s).
|
||||
pub const fn align_of<T: ?Sized + Aligned>() -> usize {
|
||||
T::ALIGN
|
||||
}
|
||||
|
||||
/// A type with a statically known alignment.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `Self::ALIGN` must be equal to the alignment of `Self`. For sized types it
|
||||
/// is [`mem::align_of<Self>()`], for unsized types it depends on the type, for
|
||||
/// example `[T]` has alignment of `T`.
|
||||
///
|
||||
/// [`mem::align_of<Self>()`]: mem::align_of
|
||||
pub unsafe trait Aligned {
|
||||
/// Alignment of `Self`.
|
||||
const ALIGN: usize;
|
||||
}
|
||||
|
||||
unsafe impl<T> Aligned for T {
|
||||
const ALIGN: usize = mem::align_of::<Self>();
|
||||
}
|
||||
|
||||
unsafe impl<T> Aligned for [T] {
|
||||
const ALIGN: usize = mem::align_of::<T>();
|
||||
}
|
@ -83,6 +83,7 @@ pub mod transitive_relation;
|
||||
pub mod vec_linked_list;
|
||||
pub mod work_queue;
|
||||
pub use atomic_ref::AtomicRef;
|
||||
pub mod aligned;
|
||||
pub mod frozen;
|
||||
pub mod owned_slice;
|
||||
pub mod sso;
|
||||
|
@ -13,12 +13,14 @@
|
||||
//! The tag must implement the `Tag` trait. We assert that the tag and `Pointer`
|
||||
//! are compatible at compile time.
|
||||
|
||||
use std::mem::{self, ManuallyDrop};
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::ops::Deref;
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::aligned::Aligned;
|
||||
|
||||
mod copy;
|
||||
mod drop;
|
||||
|
||||
@ -31,8 +33,7 @@ pub use drop::TaggedPtr;
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer returned from [`into_ptr`] must be a [valid], pointer to
|
||||
/// [`<Self as Deref>::Target`]. Note that pointers to [`Self::Target`] must be
|
||||
/// thin, even though [`Self::Target`] may not be `Sized`.
|
||||
/// [`<Self as Deref>::Target`].
|
||||
///
|
||||
/// Note that if `Self` implements [`DerefMut`] the pointer returned from
|
||||
/// [`into_ptr`] must be valid for writes (and thus calling [`NonNull::as_mut`]
|
||||
@ -110,7 +111,7 @@ pub unsafe trait Tag: Copy {
|
||||
unsafe fn from_usize(tag: usize) -> Self;
|
||||
}
|
||||
|
||||
unsafe impl<T> Pointer for Box<T> {
|
||||
unsafe impl<T: ?Sized + Aligned> Pointer for Box<T> {
|
||||
const BITS: usize = bits_for::<Self::Target>();
|
||||
|
||||
#[inline]
|
||||
@ -130,7 +131,7 @@ unsafe impl<T> Pointer for Box<T> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Pointer for Rc<T> {
|
||||
unsafe impl<T: ?Sized + Aligned> Pointer for Rc<T> {
|
||||
const BITS: usize = bits_for::<Self::Target>();
|
||||
|
||||
#[inline]
|
||||
@ -149,7 +150,7 @@ unsafe impl<T> Pointer for Rc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Pointer for Arc<T> {
|
||||
unsafe impl<T: ?Sized + Aligned> Pointer for Arc<T> {
|
||||
const BITS: usize = bits_for::<Self::Target>();
|
||||
|
||||
#[inline]
|
||||
@ -168,7 +169,7 @@ unsafe impl<T> Pointer for Arc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: 'a> Pointer for &'a T {
|
||||
unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a T {
|
||||
const BITS: usize = bits_for::<Self::Target>();
|
||||
|
||||
#[inline]
|
||||
@ -186,7 +187,7 @@ unsafe impl<'a, T: 'a> Pointer for &'a T {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: 'a> Pointer for &'a mut T {
|
||||
unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T {
|
||||
const BITS: usize = bits_for::<Self::Target>();
|
||||
|
||||
#[inline]
|
||||
@ -206,8 +207,8 @@ unsafe impl<'a, T: 'a> Pointer for &'a mut T {
|
||||
|
||||
/// Returns the number of bits available for use for tags in a pointer to `T`
|
||||
/// (this is based on `T`'s alignment).
|
||||
pub const fn bits_for<T>() -> usize {
|
||||
let bits = mem::align_of::<T>().trailing_zeros();
|
||||
pub const fn bits_for<T: ?Sized + Aligned>() -> usize {
|
||||
let bits = crate::aligned::align_of::<T>().trailing_zeros();
|
||||
|
||||
// This is a replacement for `.try_into().unwrap()` unavailable in `const`
|
||||
// (it's fine to make an assert here, since this is only called in compile time)
|
||||
|
@ -55,12 +55,7 @@ where
|
||||
}
|
||||
|
||||
const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
|
||||
const ASSERTION: () = {
|
||||
assert!(T::BITS <= P::BITS);
|
||||
// Used for the transmute_copy's below
|
||||
// TODO(waffle): do we need this assert anymore?
|
||||
assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::<usize>());
|
||||
};
|
||||
const ASSERTION: () = { assert!(T::BITS <= P::BITS) };
|
||||
|
||||
/// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`.
|
||||
///
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::arena::Arena;
|
||||
use rustc_data_structures::tagged_ptr::bits_for;
|
||||
use rustc_data_structures::aligned::Aligned;
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
use std::alloc::Layout;
|
||||
use std::cmp::Ordering;
|
||||
@ -8,7 +8,7 @@ use std::hash::{Hash, Hasher};
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
/// `List<T>` is a bit like `&[T]`, but with some critical differences.
|
||||
@ -199,20 +199,17 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
|
||||
|
||||
unsafe impl<T: Sync> Sync for List<T> {}
|
||||
|
||||
unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
|
||||
const BITS: usize = bits_for::<usize>();
|
||||
// Safety:
|
||||
// Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
|
||||
// thus aligns of `Equivalent<T>` and `List<T>` must be the same.
|
||||
unsafe impl<T> Aligned for List<T> {
|
||||
const ALIGN: usize = {
|
||||
#[repr(C)]
|
||||
struct Equivalent<T> {
|
||||
_len: usize,
|
||||
_data: [T; 0],
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_ptr(self) -> NonNull<List<T>> {
|
||||
NonNull::from(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: NonNull<List<T>>) -> &'a List<T> {
|
||||
ptr.as_ref()
|
||||
}
|
||||
|
||||
unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: NonNull<List<T>>, f: F) -> R {
|
||||
f(&ptr.as_ref())
|
||||
}
|
||||
mem::align_of::<Equivalent<T>>()
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user