Skip to content

Commit

Permalink
Constify ptr::write and the write[_unaligned] methods on *mut T
Browse files Browse the repository at this point in the history
Constify intrinsics::forget
  • Loading branch information
usbalbin committed Feb 23, 2021
1 parent 446d453 commit 89c7610
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 5 deletions.
1 change: 1 addition & 0 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,7 @@ extern "rust-intrinsic" {
///
/// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
/// `ManuallyDrop` instead.
#[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
pub fn forget<T: ?Sized>(_: T);

/// Reinterprets the bits of a value of one type as another type.
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@
#![feature(const_discriminant)]
#![feature(const_cell_into_inner)]
#![feature(const_intrinsic_copy)]
#![feature(const_intrinsic_forget)]
#![feature(const_float_classify)]
#![feature(const_float_bits_conv)]
#![feature(const_int_unchecked_arith)]
#![feature(const_mut_refs)]
#![feature(const_refs_to_cell)]
#![feature(const_cttz)]
#![feature(const_panic)]
#![feature(const_pin)]
Expand All @@ -90,6 +92,7 @@
#![feature(const_ptr_offset)]
#![feature(const_ptr_offset_from)]
#![feature(const_ptr_read)]
#![feature(const_ptr_write)]
#![feature(const_raw_ptr_comparison)]
#![feature(const_raw_ptr_deref)]
#![feature(const_slice_from_raw_parts)]
Expand Down
9 changes: 6 additions & 3 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,8 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn write<T>(dst: *mut T, src: T) {
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
pub const unsafe fn write<T>(dst: *mut T, src: T) {
// SAFETY: the caller must guarantee that `dst` is valid for writes.
// `dst` cannot overlap `src` because the caller has mutable access
// to `dst` while `src` is owned by this function.
Expand Down Expand Up @@ -998,14 +999,16 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
/// ```
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
// SAFETY: the caller must guarantee that `dst` is valid for writes.
// `dst` cannot overlap `src` because the caller has mutable access
// to `dst` while `src` is owned by this function.
unsafe {
copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
// We are calling the intrinsic directly to avoid function calls in the generated code.
intrinsics::forget(src);
}
mem::forget(src);
}

/// Performs a volatile read of the value from `src` without moving it. This
Expand Down
6 changes: 4 additions & 2 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,8 +1003,9 @@ impl<T: ?Sized> *mut T {
///
/// [`ptr::write`]: crate::ptr::write()
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
#[inline]
pub unsafe fn write(self, val: T)
pub const unsafe fn write(self, val: T)
where
T: Sized,
{
Expand Down Expand Up @@ -1057,8 +1058,9 @@ impl<T: ?Sized> *mut T {
///
/// [`ptr::write_unaligned`]: crate::ptr::write_unaligned()
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
#[inline]
pub unsafe fn write_unaligned(self, val: T)
pub const unsafe fn write_unaligned(self, val: T)
where
T: Sized,
{
Expand Down
50 changes: 50 additions & 0 deletions library/core/tests/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,53 @@ fn mut_ptr_read() {
const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
}

#[test]
fn write() {
use core::ptr;

const fn write_aligned() -> i32 {
let mut res = 0;
unsafe {
ptr::write(&mut res as *mut _, 42);
}
res
}
const ALIGNED: i32 = write_aligned();
assert_eq!(ALIGNED, 42);

const fn write_unaligned() -> [u16; 2] {
let mut two_aligned = [0u16; 2];
unsafe {
let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
ptr::write_unaligned(unaligned_ptr, u16::from_ne_bytes([0x23, 0x45]));
}
two_aligned
}
const UNALIGNED: [u16; 2] = write_unaligned();
assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
}

#[test]
fn mut_ptr_write() {
const fn aligned() -> i32 {
let mut res = 0;
unsafe {
(&mut res as *mut i32).write(42);
}
res
}
const ALIGNED: i32 = aligned();
assert_eq!(ALIGNED, 42);

const fn write_unaligned() -> [u16; 2] {
let mut two_aligned = [0u16; 2];
unsafe {
let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
unaligned_ptr.write_unaligned(u16::from_ne_bytes([0x23, 0x45]));
}
two_aligned
}
const UNALIGNED: [u16; 2] = write_unaligned();
assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
}
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#![feature(const_cell_into_inner)]
#![feature(const_maybe_uninit_assume_init)]
#![feature(const_ptr_read)]
#![feature(const_ptr_write)]
#![feature(const_ptr_offset)]
#![feature(control_flow_enum)]
#![feature(core_intrinsics)]
Expand Down

0 comments on commit 89c7610

Please sign in to comment.