split core::ptr module into multiple files
This commit is contained in:
parent
5245803120
commit
c2e7eb6ff0
|
@ -1,5 +1,3 @@
|
||||||
// ignore-tidy-filelength
|
|
||||||
|
|
||||||
//! Manually manage memory through raw pointers.
|
//! Manually manage memory through raw pointers.
|
||||||
//!
|
//!
|
||||||
//! *[See also the pointer primitive types](../../std/primitive.pointer.html).*
|
//! *[See also the pointer primitive types](../../std/primitive.pointer.html).*
|
||||||
|
@ -65,14 +63,10 @@
|
||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
use crate::convert::From;
|
|
||||||
use crate::intrinsics;
|
use crate::intrinsics;
|
||||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::hash;
|
use crate::hash;
|
||||||
use crate::marker::{PhantomData, Unsize};
|
|
||||||
use crate::mem::{self, MaybeUninit};
|
use crate::mem::{self, MaybeUninit};
|
||||||
|
|
||||||
use crate::cmp::Ordering::{self, Less, Equal, Greater};
|
use crate::cmp::Ordering::{self, Less, Equal, Greater};
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -84,6 +78,14 @@ pub use crate::intrinsics::copy;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use crate::intrinsics::write_bytes;
|
pub use crate::intrinsics::write_bytes;
|
||||||
|
|
||||||
|
mod non_null;
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
pub use non_null::NonNull;
|
||||||
|
|
||||||
|
mod unique;
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
pub use unique::Unique;
|
||||||
|
|
||||||
/// Executes the destructor (if any) of the pointed-to value.
|
/// Executes the destructor (if any) of the pointed-to value.
|
||||||
///
|
///
|
||||||
/// This is semantically equivalent to calling [`ptr::read`] and discarding
|
/// This is semantically equivalent to calling [`ptr::read`] and discarding
|
||||||
|
@ -2742,384 +2744,3 @@ impl<T: ?Sized> PartialOrd for *mut T {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ge(&self, other: &*mut T) -> bool { *self >= *other }
|
fn ge(&self, other: &*mut T) -> bool { *self >= *other }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
|
|
||||||
/// of this wrapper owns the referent. Useful for building abstractions like
|
|
||||||
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
|
|
||||||
///
|
|
||||||
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
|
|
||||||
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
|
|
||||||
/// the kind of strong aliasing guarantees an instance of `T` can expect:
|
|
||||||
/// the referent of the pointer should not be modified without a unique path to
|
|
||||||
/// its owning Unique.
|
|
||||||
///
|
|
||||||
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
|
|
||||||
/// consider using `NonNull`, which has weaker semantics.
|
|
||||||
///
|
|
||||||
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
|
|
||||||
/// is never dereferenced. This is so that enums may use this forbidden value
|
|
||||||
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
|
|
||||||
/// However the pointer may still dangle if it isn't dereferenced.
|
|
||||||
///
|
|
||||||
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
|
|
||||||
/// for any type which upholds Unique's aliasing requirements.
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0",
|
|
||||||
reason = "use NonNull instead and consider PhantomData<T> \
|
|
||||||
(if you also use #[may_dangle]), Send, and/or Sync")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
|
||||||
pub struct Unique<T: ?Sized> {
|
|
||||||
pointer: *const T,
|
|
||||||
// NOTE: this marker has no consequences for variance, but is necessary
|
|
||||||
// for dropck to understand that we logically own a `T`.
|
|
||||||
//
|
|
||||||
// For details, see:
|
|
||||||
// https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
|
|
||||||
_marker: PhantomData<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> fmt::Debug for Unique<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
|
|
||||||
/// reference is unaliased. Note that this aliasing invariant is
|
|
||||||
/// unenforced by the type system; the abstraction using the
|
|
||||||
/// `Unique` must enforce it.
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
|
|
||||||
|
|
||||||
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
|
|
||||||
/// reference is unaliased. Note that this aliasing invariant is
|
|
||||||
/// unenforced by the type system; the abstraction using the
|
|
||||||
/// `Unique` must enforce it.
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: Sized> Unique<T> {
|
|
||||||
/// Creates a new `Unique` that is dangling, but well-aligned.
|
|
||||||
///
|
|
||||||
/// This is useful for initializing types which lazily allocate, like
|
|
||||||
/// `Vec::new` does.
|
|
||||||
///
|
|
||||||
/// Note that the pointer value may potentially represent a valid pointer to
|
|
||||||
/// a `T`, which means this must not be used as a "not yet initialized"
|
|
||||||
/// sentinel value. Types that lazily allocate must track initialization by
|
|
||||||
/// some other means.
|
|
||||||
// FIXME: rename to dangling() to match NonNull?
|
|
||||||
pub const fn empty() -> Self {
|
|
||||||
unsafe {
|
|
||||||
Unique::new_unchecked(mem::align_of::<T>() as *mut T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> Unique<T> {
|
|
||||||
/// Creates a new `Unique`.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// `ptr` must be non-null.
|
|
||||||
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
|
||||||
Unique { pointer: ptr as _, _marker: PhantomData }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new `Unique` if `ptr` is non-null.
|
|
||||||
pub fn new(ptr: *mut T) -> Option<Self> {
|
|
||||||
if !ptr.is_null() {
|
|
||||||
Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Acquires the underlying `*mut` pointer.
|
|
||||||
pub const fn as_ptr(self) -> *mut T {
|
|
||||||
self.pointer as *mut T
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dereferences the content.
|
|
||||||
///
|
|
||||||
/// The resulting lifetime is bound to self so this behaves "as if"
|
|
||||||
/// it were actually an instance of T that is getting borrowed. If a longer
|
|
||||||
/// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
|
|
||||||
pub unsafe fn as_ref(&self) -> &T {
|
|
||||||
&*self.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutably dereferences the content.
|
|
||||||
///
|
|
||||||
/// The resulting lifetime is bound to self so this behaves "as if"
|
|
||||||
/// it were actually an instance of T that is getting borrowed. If a longer
|
|
||||||
/// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
|
|
||||||
pub unsafe fn as_mut(&mut self) -> &mut T {
|
|
||||||
&mut *self.as_ptr()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> Clone for Unique<T> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> Copy for Unique<T> { }
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> fmt::Pointer for Unique<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> From<&mut T> for Unique<T> {
|
|
||||||
fn from(reference: &mut T) -> Self {
|
|
||||||
unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> From<&T> for Unique<T> {
|
|
||||||
fn from(reference: &T) -> Self {
|
|
||||||
unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
|
|
||||||
fn from(p: NonNull<T>) -> Self {
|
|
||||||
unsafe { Unique { pointer: p.pointer, _marker: PhantomData } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `*mut T` but non-zero and covariant.
|
|
||||||
///
|
|
||||||
/// This is often the correct thing to use when building data structures using
|
|
||||||
/// raw pointers, but is ultimately more dangerous to use because of its additional
|
|
||||||
/// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
|
|
||||||
///
|
|
||||||
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
|
|
||||||
/// is never dereferenced. This is so that enums may use this forbidden value
|
|
||||||
/// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
|
|
||||||
/// However the pointer may still dangle if it isn't dereferenced.
|
|
||||||
///
|
|
||||||
/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
|
|
||||||
/// for your use case, you should include some [`PhantomData`] in your type to
|
|
||||||
/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
|
|
||||||
/// Usually this won't be necessary; covariance is correct for most safe abstractions,
|
|
||||||
/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they
|
|
||||||
/// provide a public API that follows the normal shared XOR mutable rules of Rust.
|
|
||||||
///
|
|
||||||
/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
|
|
||||||
/// not change the fact that mutating through a (pointer derived from a) shared
|
|
||||||
/// reference is undefined behavior unless the mutation happens inside an
|
|
||||||
/// [`UnsafeCell<T>`]. The same goes for creating a mutable reference from a shared
|
|
||||||
/// reference. When using this `From` instance without an `UnsafeCell<T>`,
|
|
||||||
/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
|
|
||||||
/// is never used for mutation.
|
|
||||||
///
|
|
||||||
/// [`PhantomData`]: ../marker/struct.PhantomData.html
|
|
||||||
/// [`UnsafeCell<T>`]: ../cell/struct.UnsafeCell.html
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
#[repr(transparent)]
|
|
||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
|
||||||
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
|
|
||||||
pub struct NonNull<T: ?Sized> {
|
|
||||||
pointer: *const T,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
|
|
||||||
// N.B., this impl is unnecessary, but should provide better error messages.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> !Send for NonNull<T> { }
|
|
||||||
|
|
||||||
/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
|
|
||||||
// N.B., this impl is unnecessary, but should provide better error messages.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> !Sync for NonNull<T> { }
|
|
||||||
|
|
||||||
impl<T: Sized> NonNull<T> {
|
|
||||||
/// Creates a new `NonNull` that is dangling, but well-aligned.
|
|
||||||
///
|
|
||||||
/// This is useful for initializing types which lazily allocate, like
|
|
||||||
/// `Vec::new` does.
|
|
||||||
///
|
|
||||||
/// Note that the pointer value may potentially represent a valid pointer to
|
|
||||||
/// a `T`, which means this must not be used as a "not yet initialized"
|
|
||||||
/// sentinel value. Types that lazily allocate must track initialization by
|
|
||||||
/// some other means.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
#[inline]
|
|
||||||
pub const fn dangling() -> Self {
|
|
||||||
unsafe {
|
|
||||||
let ptr = mem::align_of::<T>() as *mut T;
|
|
||||||
NonNull::new_unchecked(ptr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized> NonNull<T> {
|
|
||||||
/// Creates a new `NonNull`.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// `ptr` must be non-null.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
#[inline]
|
|
||||||
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
|
||||||
NonNull { pointer: ptr as _ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new `NonNull` if `ptr` is non-null.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
#[inline]
|
|
||||||
pub fn new(ptr: *mut T) -> Option<Self> {
|
|
||||||
if !ptr.is_null() {
|
|
||||||
Some(unsafe { Self::new_unchecked(ptr) })
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Acquires the underlying `*mut` pointer.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
#[inline]
|
|
||||||
pub const fn as_ptr(self) -> *mut T {
|
|
||||||
self.pointer as *mut T
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dereferences the content.
|
|
||||||
///
|
|
||||||
/// The resulting lifetime is bound to self so this behaves "as if"
|
|
||||||
/// it were actually an instance of T that is getting borrowed. If a longer
|
|
||||||
/// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn as_ref(&self) -> &T {
|
|
||||||
&*self.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutably dereferences the content.
|
|
||||||
///
|
|
||||||
/// The resulting lifetime is bound to self so this behaves "as if"
|
|
||||||
/// it were actually an instance of T that is getting borrowed. If a longer
|
|
||||||
/// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn as_mut(&mut self) -> &mut T {
|
|
||||||
&mut *self.as_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cast to a pointer of another type
|
|
||||||
#[stable(feature = "nonnull_cast", since = "1.27.0")]
|
|
||||||
#[inline]
|
|
||||||
pub const fn cast<U>(self) -> NonNull<U> {
|
|
||||||
unsafe {
|
|
||||||
NonNull::new_unchecked(self.as_ptr() as *mut U)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> Clone for NonNull<T> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> Copy for NonNull<T> { }
|
|
||||||
|
|
||||||
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
|
||||||
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
|
||||||
|
|
||||||
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
|
||||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> fmt::Debug for NonNull<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> fmt::Pointer for NonNull<T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
fmt::Pointer::fmt(&self.as_ptr(), f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> Eq for NonNull<T> {}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> PartialEq for NonNull<T> {
|
|
||||||
#[inline]
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.as_ptr() == other.as_ptr()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> Ord for NonNull<T> {
|
|
||||||
#[inline]
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
self.as_ptr().cmp(&other.as_ptr())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> PartialOrd for NonNull<T> {
|
|
||||||
#[inline]
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
self.as_ptr().partial_cmp(&other.as_ptr())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> hash::Hash for NonNull<T> {
|
|
||||||
#[inline]
|
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
|
||||||
self.as_ptr().hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "ptr_internals", issue = "0")]
|
|
||||||
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
|
||||||
#[inline]
|
|
||||||
fn from(unique: Unique<T>) -> Self {
|
|
||||||
unsafe { NonNull { pointer: unique.pointer } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> From<&mut T> for NonNull<T> {
|
|
||||||
#[inline]
|
|
||||||
fn from(reference: &mut T) -> Self {
|
|
||||||
unsafe { NonNull { pointer: reference as *mut T } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
|
||||||
impl<T: ?Sized> From<&T> for NonNull<T> {
|
|
||||||
#[inline]
|
|
||||||
fn from(reference: &T) -> Self {
|
|
||||||
unsafe { NonNull { pointer: reference as *const T } }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
use crate::convert::From;
|
||||||
|
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
|
use crate::fmt;
|
||||||
|
use crate::hash;
|
||||||
|
use crate::marker::Unsize;
|
||||||
|
use crate::mem;
|
||||||
|
use crate::ptr::Unique;
|
||||||
|
use crate::cmp::Ordering;
|
||||||
|
|
||||||
|
/// `*mut T` but non-zero and covariant.
|
||||||
|
///
|
||||||
|
/// This is often the correct thing to use when building data structures using
|
||||||
|
/// raw pointers, but is ultimately more dangerous to use because of its additional
|
||||||
|
/// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
|
||||||
|
///
|
||||||
|
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
|
||||||
|
/// is never dereferenced. This is so that enums may use this forbidden value
|
||||||
|
/// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
|
||||||
|
/// However the pointer may still dangle if it isn't dereferenced.
|
||||||
|
///
|
||||||
|
/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
|
||||||
|
/// for your use case, you should include some [`PhantomData`] in your type to
|
||||||
|
/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
|
||||||
|
/// Usually this won't be necessary; covariance is correct for most safe abstractions,
|
||||||
|
/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they
|
||||||
|
/// provide a public API that follows the normal shared XOR mutable rules of Rust.
|
||||||
|
///
|
||||||
|
/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
|
||||||
|
/// not change the fact that mutating through a (pointer derived from a) shared
|
||||||
|
/// reference is undefined behavior unless the mutation happens inside an
|
||||||
|
/// [`UnsafeCell<T>`]. The same goes for creating a mutable reference from a shared
|
||||||
|
/// reference. When using this `From` instance without an `UnsafeCell<T>`,
|
||||||
|
/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
|
||||||
|
/// is never used for mutation.
|
||||||
|
///
|
||||||
|
/// [`PhantomData`]: ../marker/struct.PhantomData.html
|
||||||
|
/// [`UnsafeCell<T>`]: ../cell/struct.UnsafeCell.html
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[rustc_layout_scalar_valid_range_start(1)]
|
||||||
|
#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
|
||||||
|
pub struct NonNull<T: ?Sized> {
|
||||||
|
pointer: *const T,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
|
||||||
|
// N.B., this impl is unnecessary, but should provide better error messages.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> !Send for NonNull<T> { }
|
||||||
|
|
||||||
|
/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
|
||||||
|
// N.B., this impl is unnecessary, but should provide better error messages.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> !Sync for NonNull<T> { }
|
||||||
|
|
||||||
|
impl<T: Sized> NonNull<T> {
|
||||||
|
/// Creates a new `NonNull` that is dangling, but well-aligned.
|
||||||
|
///
|
||||||
|
/// This is useful for initializing types which lazily allocate, like
|
||||||
|
/// `Vec::new` does.
|
||||||
|
///
|
||||||
|
/// Note that the pointer value may potentially represent a valid pointer to
|
||||||
|
/// a `T`, which means this must not be used as a "not yet initialized"
|
||||||
|
/// sentinel value. Types that lazily allocate must track initialization by
|
||||||
|
/// some other means.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn dangling() -> Self {
|
||||||
|
unsafe {
|
||||||
|
let ptr = mem::align_of::<T>() as *mut T;
|
||||||
|
NonNull::new_unchecked(ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized> NonNull<T> {
|
||||||
|
/// Creates a new `NonNull`.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `ptr` must be non-null.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
||||||
|
NonNull { pointer: ptr as _ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new `NonNull` if `ptr` is non-null.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[inline]
|
||||||
|
pub fn new(ptr: *mut T) -> Option<Self> {
|
||||||
|
if !ptr.is_null() {
|
||||||
|
Some(unsafe { Self::new_unchecked(ptr) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Acquires the underlying `*mut` pointer.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_ptr(self) -> *mut T {
|
||||||
|
self.pointer as *mut T
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereferences the content.
|
||||||
|
///
|
||||||
|
/// The resulting lifetime is bound to self so this behaves "as if"
|
||||||
|
/// it were actually an instance of T that is getting borrowed. If a longer
|
||||||
|
/// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn as_ref(&self) -> &T {
|
||||||
|
&*self.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably dereferences the content.
|
||||||
|
///
|
||||||
|
/// The resulting lifetime is bound to self so this behaves "as if"
|
||||||
|
/// it were actually an instance of T that is getting borrowed. If a longer
|
||||||
|
/// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn as_mut(&mut self) -> &mut T {
|
||||||
|
&mut *self.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cast to a pointer of another type
|
||||||
|
#[stable(feature = "nonnull_cast", since = "1.27.0")]
|
||||||
|
#[inline]
|
||||||
|
pub const fn cast<U>(self) -> NonNull<U> {
|
||||||
|
unsafe {
|
||||||
|
NonNull::new_unchecked(self.as_ptr() as *mut U)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> Clone for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> Copy for NonNull<T> { }
|
||||||
|
|
||||||
|
#[unstable(feature = "coerce_unsized", issue = "27732")]
|
||||||
|
impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
|
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
|
||||||
|
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> fmt::Debug for NonNull<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> fmt::Pointer for NonNull<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> Eq for NonNull<T> {}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> PartialEq for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.as_ptr() == other.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> Ord for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.as_ptr().cmp(&other.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> PartialOrd for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
self.as_ptr().partial_cmp(&other.as_ptr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> hash::Hash for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.as_ptr().hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(unique: Unique<T>) -> Self {
|
||||||
|
unsafe { NonNull::new_unchecked(unique.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> From<&mut T> for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(reference: &mut T) -> Self {
|
||||||
|
unsafe { NonNull { pointer: reference as *mut T } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
impl<T: ?Sized> From<&T> for NonNull<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(reference: &T) -> Self {
|
||||||
|
unsafe { NonNull { pointer: reference as *const T } }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
use crate::convert::From;
|
||||||
|
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
|
use crate::fmt;
|
||||||
|
use crate::marker::{PhantomData, Unsize};
|
||||||
|
use crate::mem;
|
||||||
|
use crate::ptr::NonNull;
|
||||||
|
|
||||||
|
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
|
||||||
|
/// of this wrapper owns the referent. Useful for building abstractions like
|
||||||
|
/// `Box<T>`, `Vec<T>`, `String`, and `HashMap<K, V>`.
|
||||||
|
///
|
||||||
|
/// Unlike `*mut T`, `Unique<T>` behaves "as if" it were an instance of `T`.
|
||||||
|
/// It implements `Send`/`Sync` if `T` is `Send`/`Sync`. It also implies
|
||||||
|
/// the kind of strong aliasing guarantees an instance of `T` can expect:
|
||||||
|
/// the referent of the pointer should not be modified without a unique path to
|
||||||
|
/// its owning Unique.
|
||||||
|
///
|
||||||
|
/// If you're uncertain of whether it's correct to use `Unique` for your purposes,
|
||||||
|
/// consider using `NonNull`, which has weaker semantics.
|
||||||
|
///
|
||||||
|
/// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
|
||||||
|
/// is never dereferenced. This is so that enums may use this forbidden value
|
||||||
|
/// as a discriminant -- `Option<Unique<T>>` has the same size as `Unique<T>`.
|
||||||
|
/// However the pointer may still dangle if it isn't dereferenced.
|
||||||
|
///
|
||||||
|
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
|
||||||
|
/// for any type which upholds Unique's aliasing requirements.
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0",
|
||||||
|
reason = "use NonNull instead and consider PhantomData<T> \
|
||||||
|
(if you also use #[may_dangle]), Send, and/or Sync")]
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[rustc_layout_scalar_valid_range_start(1)]
|
||||||
|
pub struct Unique<T: ?Sized> {
|
||||||
|
pointer: *const T,
|
||||||
|
// NOTE: this marker has no consequences for variance, but is necessary
|
||||||
|
// for dropck to understand that we logically own a `T`.
|
||||||
|
//
|
||||||
|
// For details, see:
|
||||||
|
// https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
|
||||||
|
_marker: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
|
||||||
|
/// reference is unaliased. Note that this aliasing invariant is
|
||||||
|
/// unenforced by the type system; the abstraction using the
|
||||||
|
/// `Unique` must enforce it.
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
|
||||||
|
|
||||||
|
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
|
||||||
|
/// reference is unaliased. Note that this aliasing invariant is
|
||||||
|
/// unenforced by the type system; the abstraction using the
|
||||||
|
/// `Unique` must enforce it.
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: Sized> Unique<T> {
|
||||||
|
/// Creates a new `Unique` that is dangling, but well-aligned.
|
||||||
|
///
|
||||||
|
/// This is useful for initializing types which lazily allocate, like
|
||||||
|
/// `Vec::new` does.
|
||||||
|
///
|
||||||
|
/// Note that the pointer value may potentially represent a valid pointer to
|
||||||
|
/// a `T`, which means this must not be used as a "not yet initialized"
|
||||||
|
/// sentinel value. Types that lazily allocate must track initialization by
|
||||||
|
/// some other means.
|
||||||
|
// FIXME: rename to dangling() to match NonNull?
|
||||||
|
#[inline]
|
||||||
|
pub const fn empty() -> Self {
|
||||||
|
unsafe {
|
||||||
|
Unique::new_unchecked(mem::align_of::<T>() as *mut T)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> Unique<T> {
|
||||||
|
/// Creates a new `Unique`.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `ptr` must be non-null.
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
||||||
|
Unique { pointer: ptr as _, _marker: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new `Unique` if `ptr` is non-null.
|
||||||
|
#[inline]
|
||||||
|
pub fn new(ptr: *mut T) -> Option<Self> {
|
||||||
|
if !ptr.is_null() {
|
||||||
|
Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Acquires the underlying `*mut` pointer.
|
||||||
|
#[inline]
|
||||||
|
pub const fn as_ptr(self) -> *mut T {
|
||||||
|
self.pointer as *mut T
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dereferences the content.
|
||||||
|
///
|
||||||
|
/// The resulting lifetime is bound to self so this behaves "as if"
|
||||||
|
/// it were actually an instance of T that is getting borrowed. If a longer
|
||||||
|
/// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn as_ref(&self) -> &T {
|
||||||
|
&*self.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably dereferences the content.
|
||||||
|
///
|
||||||
|
/// The resulting lifetime is bound to self so this behaves "as if"
|
||||||
|
/// it were actually an instance of T that is getting borrowed. If a longer
|
||||||
|
/// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn as_mut(&mut self) -> &mut T {
|
||||||
|
&mut *self.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> Clone for Unique<T> {
|
||||||
|
#[inline]
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> Copy for Unique<T> { }
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> fmt::Debug for Unique<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> fmt::Pointer for Unique<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Pointer::fmt(&self.as_ptr(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> From<&mut T> for Unique<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(reference: &mut T) -> Self {
|
||||||
|
unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<T: ?Sized> From<&T> for Unique<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(reference: &T) -> Self {
|
||||||
|
unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "0")]
|
||||||
|
impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
|
||||||
|
#[inline]
|
||||||
|
fn from(p: NonNull<T>) -> Self {
|
||||||
|
unsafe { Unique::new_unchecked(p.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue