Skip to content

Commit 4b9c213

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#79989 to avoid regressing performance due to using `mem::forget` over `intrinsics::forget`~~.
2 parents 351d947 + 89c7610 commit 4b9c213

File tree

6 files changed

+65
-5
lines changed

6 files changed

+65
-5
lines changed

library/core/src/intrinsics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,7 @@ extern "rust-intrinsic" {
833833
///
834834
/// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
835835
/// `ManuallyDrop` instead.
836+
#[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
836837
pub fn forget<T: ?Sized>(_: T);
837838

838839
/// Reinterprets the bits of a value of one type as another type.

library/core/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,12 @@
7373
#![feature(const_discriminant)]
7474
#![feature(const_cell_into_inner)]
7575
#![feature(const_intrinsic_copy)]
76+
#![feature(const_intrinsic_forget)]
7677
#![feature(const_float_classify)]
7778
#![feature(const_float_bits_conv)]
7879
#![feature(const_int_unchecked_arith)]
7980
#![feature(const_mut_refs)]
81+
#![feature(const_refs_to_cell)]
8082
#![feature(const_cttz)]
8183
#![feature(const_panic)]
8284
#![feature(const_pin)]
@@ -90,6 +92,7 @@
9092
#![feature(const_ptr_offset)]
9193
#![feature(const_ptr_offset_from)]
9294
#![feature(const_ptr_read)]
95+
#![feature(const_ptr_write)]
9396
#![feature(const_raw_ptr_comparison)]
9497
#![feature(const_raw_ptr_deref)]
9598
#![feature(const_slice_from_raw_parts)]

library/core/src/ptr/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,8 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
902902
/// ```
903903
#[inline]
904904
#[stable(feature = "rust1", since = "1.0.0")]
905-
pub unsafe fn write<T>(dst: *mut T, src: T) {
905+
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
906+
pub const unsafe fn write<T>(dst: *mut T, src: T) {
906907
// SAFETY: the caller must guarantee that `dst` is valid for writes.
907908
// `dst` cannot overlap `src` because the caller has mutable access
908909
// to `dst` while `src` is owned by this function.
@@ -998,14 +999,16 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
998999
/// ```
9991000
#[inline]
10001001
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
1001-
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
1002+
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
1003+
pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
10021004
// SAFETY: the caller must guarantee that `dst` is valid for writes.
10031005
// `dst` cannot overlap `src` because the caller has mutable access
10041006
// to `dst` while `src` is owned by this function.
10051007
unsafe {
10061008
copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
1009+
// We are calling the intrinsic directly to avoid function calls in the generated code.
1010+
intrinsics::forget(src);
10071011
}
1008-
mem::forget(src);
10091012
}
10101013

10111014
/// Performs a volatile read of the value from `src` without moving it. This

library/core/src/ptr/mut_ptr.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1003,8 +1003,9 @@ impl<T: ?Sized> *mut T {
10031003
///
10041004
/// [`ptr::write`]: crate::ptr::write()
10051005
#[stable(feature = "pointer_methods", since = "1.26.0")]
1006+
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
10061007
#[inline]
1007-
pub unsafe fn write(self, val: T)
1008+
pub const unsafe fn write(self, val: T)
10081009
where
10091010
T: Sized,
10101011
{
@@ -1057,8 +1058,9 @@ impl<T: ?Sized> *mut T {
10571058
///
10581059
/// [`ptr::write_unaligned`]: crate::ptr::write_unaligned()
10591060
#[stable(feature = "pointer_methods", since = "1.26.0")]
1061+
#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
10601062
#[inline]
1061-
pub unsafe fn write_unaligned(self, val: T)
1063+
pub const unsafe fn write_unaligned(self, val: T)
10621064
where
10631065
T: Sized,
10641066
{

library/core/tests/const_ptr.rs

+50
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,53 @@ fn mut_ptr_read() {
4949
const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
5050
assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
5151
}
52+
53+
#[test]
54+
fn write() {
55+
use core::ptr;
56+
57+
const fn write_aligned() -> i32 {
58+
let mut res = 0;
59+
unsafe {
60+
ptr::write(&mut res as *mut _, 42);
61+
}
62+
res
63+
}
64+
const ALIGNED: i32 = write_aligned();
65+
assert_eq!(ALIGNED, 42);
66+
67+
const fn write_unaligned() -> [u16; 2] {
68+
let mut two_aligned = [0u16; 2];
69+
unsafe {
70+
let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
71+
ptr::write_unaligned(unaligned_ptr, u16::from_ne_bytes([0x23, 0x45]));
72+
}
73+
two_aligned
74+
}
75+
const UNALIGNED: [u16; 2] = write_unaligned();
76+
assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
77+
}
78+
79+
#[test]
80+
fn mut_ptr_write() {
81+
const fn aligned() -> i32 {
82+
let mut res = 0;
83+
unsafe {
84+
(&mut res as *mut i32).write(42);
85+
}
86+
res
87+
}
88+
const ALIGNED: i32 = aligned();
89+
assert_eq!(ALIGNED, 42);
90+
91+
const fn write_unaligned() -> [u16; 2] {
92+
let mut two_aligned = [0u16; 2];
93+
unsafe {
94+
let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
95+
unaligned_ptr.write_unaligned(u16::from_ne_bytes([0x23, 0x45]));
96+
}
97+
two_aligned
98+
}
99+
const UNALIGNED: [u16; 2] = write_unaligned();
100+
assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
101+
}

library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#![feature(const_cell_into_inner)]
1515
#![feature(const_maybe_uninit_assume_init)]
1616
#![feature(const_ptr_read)]
17+
#![feature(const_ptr_write)]
1718
#![feature(const_ptr_offset)]
1819
#![feature(control_flow_enum)]
1920
#![feature(core_intrinsics)]

0 commit comments

Comments
 (0)