Skip to content

Commit 937d580

Browse files
committed
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`.
1 parent 9ab83b9 commit 937d580

File tree

5 files changed

+86
-8
lines changed

5 files changed

+86
-8
lines changed

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
#![feature(auto_traits)]
124124
#![feature(or_patterns)]
125125
#![feature(prelude_import)]
126+
#![cfg_attr(not(bootstrap), feature(ptr_metadata))]
126127
#![feature(repr_simd, platform_intrinsics)]
127128
#![feature(rustc_attrs)]
128129
#![feature(simd_ffi)]

library/core/src/ptr/metadata.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,48 @@ pub fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
3636
unsafe { PtrRepr { const_ptr: ptr }.components.metadata }
3737
}
3838

39+
/// Forms a raw pointer from a data address and metadata.
40+
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
41+
#[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
42+
#[inline]
43+
pub const fn from_raw_parts<T: ?Sized>(
44+
data_address: *const (),
45+
metadata: <T as Pointee>::Metadata,
46+
) -> *const T {
47+
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
48+
// and PtrComponents<T> have the same memory layouts. Only std can make this
49+
// guarantee.
50+
unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.const_ptr }
51+
}
52+
53+
/// Performs the same functionality as [`from_raw_parts`], except that a
54+
/// raw `*mut` pointer is returned, as opposed to a raw `*const` pointer.
55+
///
56+
/// See the documentation of [`from_raw_parts`] for more details.
57+
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
58+
#[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
59+
#[inline]
60+
pub const fn from_raw_parts_mut<T: ?Sized>(
61+
data_address: *mut (),
62+
metadata: <T as Pointee>::Metadata,
63+
) -> *mut T {
64+
// SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
65+
// and PtrComponents<T> have the same memory layouts. Only std can make this
66+
// guarantee.
67+
unsafe { PtrRepr { components: PtrComponents { data_address, metadata } }.mut_ptr }
68+
}
69+
3970
#[repr(C)]
40-
union PtrRepr<T: ?Sized> {
41-
const_ptr: *const T,
42-
components: PtrComponents<T>,
71+
pub(crate) union PtrRepr<T: ?Sized> {
72+
pub(crate) const_ptr: *const T,
73+
pub(crate) mut_ptr: *mut T,
74+
pub(crate) components: PtrComponents<T>,
4375
}
4476

4577
#[repr(C)]
46-
struct PtrComponents<T: ?Sized> {
47-
data_address: usize,
48-
metadata: <T as Pointee>::Metadata,
78+
pub(crate) struct PtrComponents<T: ?Sized> {
79+
pub(crate) data_address: *const (),
80+
pub(crate) metadata: <T as Pointee>::Metadata,
4981
}
5082

5183
// Manual impl needed to avoid `T: Copy` bound.

library/core/src/ptr/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub use crate::intrinsics::write_bytes;
8686
mod metadata;
8787
#[cfg(not(bootstrap))]
8888
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
89-
pub use metadata::{metadata, DynMetadata, Pointee, Thin};
89+
pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin};
9090

9191
mod non_null;
9292
#[stable(feature = "nonnull", since = "1.25.0")]

library/core/src/ptr/non_null.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,24 @@ impl<T: ?Sized> NonNull<T> {
175175
}
176176
}
177177

178+
/// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a
179+
/// `NonNull` pointer is returned, as opposed to a raw `*const` pointer.
180+
///
181+
/// See the documentation of [`std::ptr::from_raw_parts`] for more details.
182+
#[cfg(not(bootstrap))]
183+
#[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
184+
#[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")]
185+
#[inline]
186+
pub const fn from_raw_parts(
187+
data_address: NonNull<()>,
188+
metadata: <T as super::Pointee>::Metadata,
189+
) -> NonNull<T> {
190+
// SAFETY: The result of `ptr::from::raw_parts_mut` is non-null because `data_address` is.
191+
unsafe {
192+
NonNull::new_unchecked(super::from_raw_parts_mut(data_address.as_ptr(), metadata))
193+
}
194+
}
195+
178196
/// Acquires the underlying `*mut` pointer.
179197
#[stable(feature = "nonnull", since = "1.25.0")]
180198
#[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]

library/core/tests/ptr.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::cell::RefCell;
2-
use core::ptr::*;
2+
use core::ptr::{self, *};
33
use std::fmt::{Debug, Display};
44

55
#[test]
@@ -525,3 +525,30 @@ fn dyn_metadata() {
525525

526526
assert!(format!("{:?}", meta).starts_with("DynMetadata(0x"));
527527
}
528+
529+
#[test]
530+
#[cfg(not(bootstrap))]
531+
fn from_raw_parts() {
532+
let mut value = 5_u32;
533+
let address = &mut value as *mut _ as *mut ();
534+
let trait_object: &dyn Display = &mut value;
535+
let vtable = metadata(trait_object);
536+
let trait_object = NonNull::from(trait_object);
537+
538+
assert_eq!(ptr::from_raw_parts(address, vtable), trait_object.as_ptr());
539+
assert_eq!(ptr::from_raw_parts_mut(address, vtable), trait_object.as_ptr());
540+
assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), vtable), trait_object);
541+
542+
let mut array = [5_u32, 5, 5, 5, 5];
543+
let address = &mut array as *mut _ as *mut ();
544+
let array_ptr = NonNull::from(&mut array);
545+
let slice_ptr = NonNull::from(&mut array[..]);
546+
547+
assert_eq!(ptr::from_raw_parts(address, ()), array_ptr.as_ptr());
548+
assert_eq!(ptr::from_raw_parts_mut(address, ()), array_ptr.as_ptr());
549+
assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), ()), array_ptr);
550+
551+
assert_eq!(ptr::from_raw_parts(address, 5), slice_ptr.as_ptr());
552+
assert_eq!(ptr::from_raw_parts_mut(address, 5), slice_ptr.as_ptr());
553+
assert_eq!(NonNull::from_raw_parts(NonNull::new(address).unwrap(), 5), slice_ptr);
554+
}

0 commit comments

Comments
 (0)