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 vec_linked_list;
|
||||||
pub mod work_queue;
|
pub mod work_queue;
|
||||||
pub use atomic_ref::AtomicRef;
|
pub use atomic_ref::AtomicRef;
|
||||||
|
pub mod aligned;
|
||||||
pub mod frozen;
|
pub mod frozen;
|
||||||
pub mod owned_slice;
|
pub mod owned_slice;
|
||||||
pub mod sso;
|
pub mod sso;
|
||||||
|
@ -13,12 +13,14 @@
|
|||||||
//! The tag must implement the `Tag` trait. We assert that the tag and `Pointer`
|
//! The tag must implement the `Tag` trait. We assert that the tag and `Pointer`
|
||||||
//! are compatible at compile time.
|
//! are compatible at compile time.
|
||||||
|
|
||||||
use std::mem::{self, ManuallyDrop};
|
use std::mem::ManuallyDrop;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use crate::aligned::Aligned;
|
||||||
|
|
||||||
mod copy;
|
mod copy;
|
||||||
mod drop;
|
mod drop;
|
||||||
|
|
||||||
@ -31,8 +33,7 @@ pub use drop::TaggedPtr;
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// The pointer returned from [`into_ptr`] must be a [valid], pointer to
|
/// The pointer returned from [`into_ptr`] must be a [valid], pointer to
|
||||||
/// [`<Self as Deref>::Target`]. Note that pointers to [`Self::Target`] must be
|
/// [`<Self as Deref>::Target`].
|
||||||
/// thin, even though [`Self::Target`] may not be `Sized`.
|
|
||||||
///
|
///
|
||||||
/// Note that if `Self` implements [`DerefMut`] the pointer returned from
|
/// Note that if `Self` implements [`DerefMut`] the pointer returned from
|
||||||
/// [`into_ptr`] must be valid for writes (and thus calling [`NonNull::as_mut`]
|
/// [`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 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>();
|
const BITS: usize = bits_for::<Self::Target>();
|
||||||
|
|
||||||
#[inline]
|
#[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>();
|
const BITS: usize = bits_for::<Self::Target>();
|
||||||
|
|
||||||
#[inline]
|
#[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>();
|
const BITS: usize = bits_for::<Self::Target>();
|
||||||
|
|
||||||
#[inline]
|
#[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>();
|
const BITS: usize = bits_for::<Self::Target>();
|
||||||
|
|
||||||
#[inline]
|
#[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>();
|
const BITS: usize = bits_for::<Self::Target>();
|
||||||
|
|
||||||
#[inline]
|
#[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`
|
/// Returns the number of bits available for use for tags in a pointer to `T`
|
||||||
/// (this is based on `T`'s alignment).
|
/// (this is based on `T`'s alignment).
|
||||||
pub const fn bits_for<T>() -> usize {
|
pub const fn bits_for<T: ?Sized + Aligned>() -> usize {
|
||||||
let bits = mem::align_of::<T>().trailing_zeros();
|
let bits = crate::aligned::align_of::<T>().trailing_zeros();
|
||||||
|
|
||||||
// This is a replacement for `.try_into().unwrap()` unavailable in `const`
|
// 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)
|
// (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 TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
|
||||||
const ASSERTION: () = {
|
const ASSERTION: () = { assert!(T::BITS <= P::BITS) };
|
||||||
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>());
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`.
|
/// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`.
|
||||||
///
|
///
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::arena::Arena;
|
use crate::arena::Arena;
|
||||||
use rustc_data_structures::tagged_ptr::bits_for;
|
use rustc_data_structures::aligned::Aligned;
|
||||||
use rustc_serialize::{Encodable, Encoder};
|
use rustc_serialize::{Encodable, Encoder};
|
||||||
use std::alloc::Layout;
|
use std::alloc::Layout;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -8,7 +8,7 @@ use std::hash::{Hash, Hasher};
|
|||||||
use std::iter;
|
use std::iter;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr::{self, NonNull};
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
/// `List<T>` is a bit like `&[T]`, but with some critical differences.
|
/// `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<T: Sync> Sync for List<T> {}
|
||||||
|
|
||||||
unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
|
// Safety:
|
||||||
const BITS: usize = bits_for::<usize>();
|
// 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]
|
mem::align_of::<Equivalent<T>>()
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user