Implement core::ptr::Unique on top of NonNull
Removes the use `rustc_layout_scalar_valid_range_start` and some `unsafe` blocks.
This commit is contained in:
@@ -119,12 +119,14 @@
|
|||||||
#![feature(const_likely)]
|
#![feature(const_likely)]
|
||||||
#![feature(const_maybe_uninit_as_mut_ptr)]
|
#![feature(const_maybe_uninit_as_mut_ptr)]
|
||||||
#![feature(const_maybe_uninit_assume_init)]
|
#![feature(const_maybe_uninit_assume_init)]
|
||||||
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_num_from_num)]
|
#![feature(const_num_from_num)]
|
||||||
#![feature(const_ops)]
|
#![feature(const_ops)]
|
||||||
#![feature(const_option)]
|
#![feature(const_option)]
|
||||||
#![feature(const_option_ext)]
|
#![feature(const_option_ext)]
|
||||||
#![feature(const_pin)]
|
#![feature(const_pin)]
|
||||||
#![feature(const_replace)]
|
#![feature(const_replace)]
|
||||||
|
#![feature(const_ptr_as_ref)]
|
||||||
#![feature(const_ptr_is_null)]
|
#![feature(const_ptr_is_null)]
|
||||||
#![feature(const_ptr_offset_from)]
|
#![feature(const_ptr_offset_from)]
|
||||||
#![feature(const_ptr_read)]
|
#![feature(const_ptr_read)]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::convert::From;
|
use crate::convert::From;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::marker::{PhantomData, Unsize};
|
use crate::marker::{PhantomData, Unsize};
|
||||||
use crate::mem;
|
|
||||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||||
|
use crate::ptr::NonNull;
|
||||||
|
|
||||||
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
|
/// 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
|
/// of this wrapper owns the referent. Useful for building abstractions like
|
||||||
@@ -32,9 +32,8 @@ use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
|||||||
)]
|
)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[rustc_layout_scalar_valid_range_start(1)]
|
|
||||||
pub struct Unique<T: ?Sized> {
|
pub struct Unique<T: ?Sized> {
|
||||||
pointer: *const T,
|
pointer: NonNull<T>,
|
||||||
// NOTE: this marker has no consequences for variance, but is necessary
|
// NOTE: this marker has no consequences for variance, but is necessary
|
||||||
// for dropck to understand that we logically own a `T`.
|
// for dropck to understand that we logically own a `T`.
|
||||||
//
|
//
|
||||||
@@ -71,9 +70,7 @@ impl<T: Sized> Unique<T> {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn dangling() -> Self {
|
pub const fn dangling() -> Self {
|
||||||
// SAFETY: mem::align_of() returns a valid, non-null pointer. The
|
Self::from(NonNull::dangling())
|
||||||
// conditions to call new_unchecked() are thus respected.
|
|
||||||
unsafe { Unique::new_unchecked(crate::ptr::invalid_mut::<T>(mem::align_of::<T>())) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,15 +84,14 @@ impl<T: ?Sized> Unique<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
|
||||||
// SAFETY: the caller must guarantee that `ptr` is non-null.
|
// SAFETY: the caller must guarantee that `ptr` is non-null.
|
||||||
unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }
|
unsafe { Unique { pointer: NonNull::new_unchecked(ptr), _marker: PhantomData } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `Unique` if `ptr` is non-null.
|
/// Creates a new `Unique` if `ptr` is non-null.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(ptr: *mut T) -> Option<Self> {
|
pub const fn new(ptr: *mut T) -> Option<Self> {
|
||||||
if !ptr.is_null() {
|
if let Some(pointer) = NonNull::new(ptr) {
|
||||||
// SAFETY: The pointer has already been checked and is not null.
|
Some(Unique { pointer, _marker: PhantomData })
|
||||||
Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } })
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -105,7 +101,7 @@ impl<T: ?Sized> Unique<T> {
|
|||||||
#[must_use = "`self` will be dropped if the result is not used"]
|
#[must_use = "`self` will be dropped if the result is not used"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn as_ptr(self) -> *mut T {
|
pub const fn as_ptr(self) -> *mut T {
|
||||||
self.pointer as *mut T
|
self.pointer.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dereferences the content.
|
/// Dereferences the content.
|
||||||
@@ -118,7 +114,7 @@ impl<T: ?Sized> Unique<T> {
|
|||||||
pub const unsafe fn as_ref(&self) -> &T {
|
pub const unsafe fn as_ref(&self) -> &T {
|
||||||
// SAFETY: the caller must guarantee that `self` meets all the
|
// SAFETY: the caller must guarantee that `self` meets all the
|
||||||
// requirements for a reference.
|
// requirements for a reference.
|
||||||
unsafe { &*self.as_ptr() }
|
unsafe { self.pointer.as_ref() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutably dereferences the content.
|
/// Mutably dereferences the content.
|
||||||
@@ -131,17 +127,14 @@ impl<T: ?Sized> Unique<T> {
|
|||||||
pub const unsafe fn as_mut(&mut self) -> &mut T {
|
pub const unsafe fn as_mut(&mut self) -> &mut T {
|
||||||
// SAFETY: the caller must guarantee that `self` meets all the
|
// SAFETY: the caller must guarantee that `self` meets all the
|
||||||
// requirements for a mutable reference.
|
// requirements for a mutable reference.
|
||||||
unsafe { &mut *self.as_ptr() }
|
unsafe { self.pointer.as_mut() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Casts to a pointer of another type.
|
/// Casts to a pointer of another type.
|
||||||
#[must_use = "`self` will be dropped if the result is not used"]
|
#[must_use = "`self` will be dropped if the result is not used"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn cast<U>(self) -> Unique<U> {
|
pub const fn cast<U>(self) -> Unique<U> {
|
||||||
// SAFETY: Unique::new_unchecked() creates a new unique and needs
|
Unique::from(self.pointer.cast())
|
||||||
// the given pointer to not be null.
|
|
||||||
// Since we are passing self as a pointer, it cannot be null.
|
|
||||||
unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +177,17 @@ impl<T: ?Sized> const From<&mut T> for Unique<T> {
|
|||||||
/// This conversion is infallible since references cannot be null.
|
/// This conversion is infallible since references cannot be null.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(reference: &mut T) -> Self {
|
fn from(reference: &mut T) -> Self {
|
||||||
// SAFETY: A mutable reference cannot be null
|
Self::from(NonNull::from(reference))
|
||||||
unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "ptr_internals", issue = "none")]
|
||||||
|
impl<T: ?Sized> const From<NonNull<T>> for Unique<T> {
|
||||||
|
/// Converts a `NonNull<T>` to a `Unique<T>`.
|
||||||
|
///
|
||||||
|
/// This conversion is infallible since `NonNull` cannot be null.
|
||||||
|
#[inline]
|
||||||
|
fn from(pointer: NonNull<T>) -> Self {
|
||||||
|
Unique { pointer, _marker: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user