Rollup merge of #81167 - usbalbin:const_write, r=oli-obk
Make ptr::write const ~~The code in this PR as of right now is not much more than an experiment.~~ ~~This should, if I am not mistaken, in theory compile and pass the tests once the bootstraping compiler is updated. Thus the PR is blocked on that which should happen some time after the February the 9th. Also we might want to wait for #79989 to avoid regressing performance due to using `mem::forget` over `intrinsics::forget`~~.
This commit is contained in:
commit
4b9c213d6f
@ -833,6 +833,7 @@
|
||||
///
|
||||
/// 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.
|
||||
|
@ -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)]
|
||||
|
@ -902,7 +902,8 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: 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.
|
||||
@ -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
|
||||
|
@ -1003,8 +1003,9 @@ pub unsafe fn drop_in_place(self) {
|
||||
///
|
||||
/// [`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 @@ pub unsafe fn write_volatile(self, val: 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,
|
||||
{
|
||||
|
@ -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])]);
|
||||
}
|
||||
|
@ -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)]
|
||||
|
Loading…
Reference in New Issue
Block a user