Add ptr::from_raw_parts
, ptr::from_raw_parts_mut
, and NonNull::from_raw_parts
The use of module-level functions instead of associated functions on `<*const T>` or `<*mut T>` follows the precedent of `ptr::slice_from_raw_parts` and `ptr::slice_from_raw_parts_mut`.
This commit is contained in:
parent
9ab83b9338
commit
937d580a25
5 changed files with 87 additions and 9 deletions
|
@ -123,6 +123,7 @@
|
|||
#![feature(auto_traits)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(prelude_import)]
|
||||
#![cfg_attr(not(bootstrap), feature(ptr_metadata))]
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(simd_ffi)]
|
||||
|
|
|
@ -36,16 +36,48 @@ pub fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
|||
unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
union PtrRepr<T: ?Sized> {
|
||||
const_ptr: *const T,
|
||||
components: PtrComponents<T>,
|
||||
/// Forms a raw pointer from a data address and metadata.
|
||||
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
|
||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
|
||||
#[inline]
|
||||
pub const fn from_raw_parts<T: ?Sized>(
|
||||
data_address: *const (),
|
||||
metadata: <T as Pointee>::Metadata,
|
||||
) -> *const T {
|
||||
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
|
||||
// and PtrComponents<T> have the same memory layouts. Only std can make this
|
||||
// guarantee.
|
||||
unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.const_ptr }
|
||||
}
|
||||
|
||||
/// Performs the same functionality as [`from_raw_parts`], except that a
|
||||
/// raw `*mut` pointer is returned, as opposed to a raw `*const` pointer.
|
||||
///
|
||||
/// See the documentation of [`from_raw_parts`] for more details.
|
||||
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
|
||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
|
||||
#[inline]
|
||||
pub const fn from_raw_parts_mut<T: ?Sized>(
|
||||
data_address: *mut (),
|
||||
metadata: <T as Pointee>::Metadata,
|
||||
) -> *mut T {
|
||||
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
|
||||
// and PtrComponents<T> have the same memory layouts. Only std can make this
|
||||
// guarantee.
|
||||
unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.mut_ptr }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct PtrComponents<T: ?Sized> {
|
||||
data_address: usize,
|
||||
metadata: <T as Pointee>::Metadata,
|
||||
pub(crate) union PtrRepr<T: ?Sized> {
|
||||
pub(crate) const_ptr: *const T,
|
||||
pub(crate) mut_ptr: *mut T,
|
||||
pub(crate) components: PtrComponents<T>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct PtrComponents<T: ?Sized> {
|
||||
pub(crate) data_address: *const (),
|
||||
pub(crate) metadata: <T as Pointee>::Metadata,
|
||||
}
|
||||
|
||||
// Manual impl needed to avoid `T: Copy` bound.
|
||||
|
|
|
@ -86,7 +86,7 @@ pub use crate::intrinsics::write_bytes;
|
|||
mod metadata;
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
|
||||
pub use metadata::{metadata, DynMetadata, Pointee, Thin};
|
||||
pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin};
|
||||
|
||||
mod non_null;
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
|
|
|
@ -175,6 +175,24 @@ impl<T: ?Sized> NonNull<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a
|
||||
/// `NonNull` pointer is returned, as opposed to a raw `*const` pointer.
|
||||
///
|
||||
/// See the documentation of [`std::ptr::from_raw_parts`] for more details.
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
|
||||
#[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
|
||||
#[inline]
|
||||
pub const fn from_raw_parts(
|
||||
data_address: NonNull<()>,
|
||||
metadata: <T as super::Pointee>::Metadata,
|
||||
) -> NonNull<T> {
|
||||
// SAFETY: The result of `ptr::from::raw_parts_mut` is non-null because `data_address` is.
|
||||
unsafe {
|
||||
NonNull::new_unchecked(super::from_raw_parts_mut(data_address.as_ptr(), metadata))
|
||||
}
|
||||
}
|
||||
|
||||
/// Acquires the underlying `*mut` pointer.
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
#[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use core::cell::RefCell;
|
||||
use core::ptr::*;
|
||||
use core::ptr::{self, *};
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
#[test]
|
||||
|
@ -525,3 +525,30 @@ fn dyn_metadata() {
|
|||
|
||||
assert!(format!("{:?}", meta).starts_with("DynMetadata(0x"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(bootstrap))]
|
||||
fn from_raw_parts() {
|
||||
let mut value = 5_u32;
|
||||
let address = &mut value as *mut _ as *mut ();
|
||||
let trait_object: &dyn Display = &mut value;
|
||||
let vtable = metadata(trait_object);
|
||||
let trait_object = NonNull::from(trait_object);
|
||||
|
||||
assert_eq!(ptr::from_raw_parts(address, vtable), trait_object.as_ptr());
|
||||
assert_eq!(ptr::from_raw_parts_mut(address, vtable), trait_object.as_ptr());
|
||||
assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), vtable), trait_object);
|
||||
|
||||
let mut array = [5_u32, 5, 5, 5, 5];
|
||||
let address = &mut array as *mut _ as *mut ();
|
||||
let array_ptr = NonNull::from(&mut array);
|
||||
let slice_ptr = NonNull::from(&mut array[..]);
|
||||
|
||||
assert_eq!(ptr::from_raw_parts(address, ()), array_ptr.as_ptr());
|
||||
assert_eq!(ptr::from_raw_parts_mut(address, ()), array_ptr.as_ptr());
|
||||
assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), ()), array_ptr);
|
||||
|
||||
assert_eq!(ptr::from_raw_parts(address, 5), slice_ptr.as_ptr());
|
||||
assert_eq!(ptr::from_raw_parts_mut(address, 5), slice_ptr.as_ptr());
|
||||
assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), 5), slice_ptr);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue