From 89c761058ab75334d864283c5881d59f7fad33c2 Mon Sep 17 00:00:00 2001 From: Albin Hedman Date: Mon, 18 Jan 2021 22:59:56 +0100 Subject: [PATCH] Constify ptr::write and the write[_unaligned] methods on *mut T Constify intrinsics::forget --- library/core/src/intrinsics.rs | 1 + library/core/src/lib.rs | 3 ++ library/core/src/ptr/mod.rs | 9 ++++-- library/core/src/ptr/mut_ptr.rs | 6 ++-- library/core/tests/const_ptr.rs | 50 +++++++++++++++++++++++++++++++++ library/core/tests/lib.rs | 1 + 6 files changed, 65 insertions(+), 5 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index a9e2ef4251a..5274262ded2 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -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); /// Reinterprets the bits of a value of one type as another type. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0d1a09a528d..64e2a951309 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -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)] @@ -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)] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 9c53430ce35..481d5d772b4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -902,7 +902,8 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -pub unsafe fn write(dst: *mut T, src: T) { +#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")] +pub const unsafe fn write(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. @@ -998,14 +999,16 @@ pub unsafe fn write(dst: *mut T, src: T) { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -pub unsafe fn write_unaligned(dst: *mut T, src: T) { +#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")] +pub const unsafe fn write_unaligned(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::()); + // 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 diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6651c3dd4e8..4e3e88b946c 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1003,8 +1003,9 @@ impl *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, { @@ -1057,8 +1058,9 @@ impl *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, { diff --git a/library/core/tests/const_ptr.rs b/library/core/tests/const_ptr.rs index 4acd059ab03..152fed803ec 100644 --- a/library/core/tests/const_ptr.rs +++ b/library/core/tests/const_ptr.rs @@ -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])]); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 9692724545f..d6d3111e2ff 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -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)]