Skip to content

Commit 0a43923

Browse files
committed
Auto merge of #97419 - WaffleLapkin:const_from_ptr_range, r=oli-obk
Make `from{,_mut}_ptr_range` const This PR makes the following APIs `const`: ```rust // core::slice pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T]; pub const unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T]; ``` Tracking issue: #89792. Feature for `from_ptr_range` as a `const fn`: `slice_from_ptr_range_const`. Feature for `from_mut_ptr_range` as a `const fn`: `slice_from_mut_ptr_range_const`. r? `@oli-obk`
2 parents 16a0d03 + 3a2bb78 commit 0a43923

File tree

7 files changed

+772
-2
lines changed

7 files changed

+772
-2
lines changed

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
#![feature(ptr_sub_ptr)]
131131
#![feature(receiver_trait)]
132132
#![feature(set_ptr_value)]
133+
#![feature(slice_from_ptr_range)]
133134
#![feature(slice_group_by)]
134135
#![feature(slice_ptr_get)]
135136
#![feature(slice_ptr_len)]

library/alloc/src/slice.rs

+2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ pub use core::slice::EscapeAscii;
114114
pub use core::slice::SliceIndex;
115115
#[stable(feature = "from_ref", since = "1.28.0")]
116116
pub use core::slice::{from_mut, from_ref};
117+
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
118+
pub use core::slice::{from_mut_ptr_range, from_ptr_range};
117119
#[stable(feature = "rust1", since = "1.0.0")]
118120
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
119121
#[stable(feature = "rust1", since = "1.0.0")]

library/core/src/slice/raw.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
213213
///
214214
/// [valid]: ptr#safety
215215
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
216-
pub unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
216+
#[rustc_const_unstable(feature = "const_slice_from_ptr_range", issue = "89792")]
217+
pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
217218
// SAFETY: the caller must uphold the safety contract for `from_ptr_range`.
218219
unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
219220
}
@@ -263,7 +264,8 @@ pub unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
263264
///
264265
/// [valid]: ptr#safety
265266
#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
266-
pub unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] {
267+
#[rustc_const_unstable(feature = "slice_from_mut_ptr_range_const", issue = "89792")]
268+
pub const unsafe fn from_mut_ptr_range<'a, T>(range: Range<*mut T>) -> &'a mut [T] {
267269
// SAFETY: the caller must uphold the safety contract for `from_mut_ptr_range`.
268270
unsafe { from_raw_parts_mut(range.start, range.end.sub_ptr(range.start)) }
269271
}
+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// run-pass
2+
#![feature(
3+
const_slice_from_raw_parts,
4+
slice_from_ptr_range,
5+
const_slice_from_ptr_range,
6+
pointer_byte_offsets,
7+
const_pointer_byte_offsets
8+
)]
9+
use std::{
10+
mem::MaybeUninit,
11+
ptr,
12+
slice::{from_ptr_range, from_raw_parts},
13+
};
14+
15+
// Dangling is ok, as long as it's either for ZST reads or for no reads
16+
pub static S0: &[u32] = unsafe { from_raw_parts(dangling(), 0) };
17+
pub static S1: &[()] = unsafe { from_raw_parts(dangling(), 3) };
18+
19+
// References are always valid of reads of a single element (basically `slice::from_ref`)
20+
pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 1) };
21+
pub static S3: &[MaybeUninit<&u32>] = unsafe { from_raw_parts(&D1, 1) };
22+
23+
// Reinterpreting data is fine, as long as layouts match
24+
pub static S4: &[u8] = unsafe { from_raw_parts((&D0) as *const _ as _, 3) };
25+
// This is only valid because D1 has uninitialized bytes, if it was an initialized pointer,
26+
// that would reinterpret pointers as integers which is UB in CTFE.
27+
pub static S5: &[MaybeUninit<u8>] = unsafe { from_raw_parts((&D1) as *const _ as _, 2) };
28+
// Even though u32 and [bool; 4] have different layouts, D0 has a value that
29+
// is valid as [bool; 4], so this is not UB (it's basically a transmute)
30+
pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
31+
32+
// Structs are considered single allocated objects,
33+
// as long as you don't reinterpret padding as initialized
34+
// data everything is ok.
35+
pub static S7: &[u16] = unsafe {
36+
let ptr = (&D2 as *const Struct as *const u16).byte_add(4);
37+
38+
from_raw_parts(ptr, 3)
39+
};
40+
pub static S8: &[MaybeUninit<u16>] = unsafe {
41+
let ptr = &D2 as *const Struct as *const MaybeUninit<u16>;
42+
43+
from_raw_parts(ptr, 6)
44+
};
45+
46+
pub static R0: &[u32] = unsafe { from_ptr_range(dangling()..dangling()) };
47+
// from_ptr_range panics on zst
48+
//pub static R1: &[()] = unsafe { from_ptr_range(dangling(), dangling().byte_add(3)) };
49+
pub static R2: &[u32] = unsafe {
50+
let ptr = &D0 as *const u32;
51+
from_ptr_range(ptr..ptr.add(1))
52+
};
53+
pub static R3: &[MaybeUninit<&u32>] = unsafe {
54+
let ptr = &D1 as *const MaybeUninit<&u32>;
55+
from_ptr_range(ptr..ptr.add(1))
56+
};
57+
pub static R4: &[u8] = unsafe {
58+
let ptr = &D0 as *const u32 as *const u8;
59+
from_ptr_range(ptr..ptr.add(3))
60+
};
61+
pub static R5: &[MaybeUninit<u8>] = unsafe {
62+
let ptr = &D1 as *const MaybeUninit<&u32> as *const MaybeUninit<u8>;
63+
from_ptr_range(ptr..ptr.add(2))
64+
};
65+
pub static R6: &[bool] = unsafe {
66+
let ptr = &D0 as *const u32 as *const bool;
67+
from_ptr_range(ptr..ptr.add(4))
68+
};
69+
pub static R7: &[u16] = unsafe {
70+
let d2 = &D2;
71+
let l = &d2.b as *const u32 as *const u16;
72+
let r = &d2.d as *const u8 as *const u16;
73+
74+
from_ptr_range(l..r)
75+
};
76+
pub static R8: &[MaybeUninit<u16>] = unsafe {
77+
let d2 = &D2;
78+
let l = d2 as *const Struct as *const MaybeUninit<u16>;
79+
let r = &d2.d as *const u8 as *const MaybeUninit<u16>;
80+
81+
from_ptr_range(l..r)
82+
};
83+
84+
// Using valid slice is always valid
85+
pub static R9: &[u32] = unsafe { from_ptr_range(R0.as_ptr_range()) };
86+
pub static R10: &[u32] = unsafe { from_ptr_range(R2.as_ptr_range()) };
87+
88+
const D0: u32 = (1 << 16) | 1;
89+
const D1: MaybeUninit<&u32> = MaybeUninit::uninit();
90+
const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 };
91+
92+
const fn dangling<T>() -> *const T {
93+
ptr::NonNull::dangling().as_ptr() as _
94+
}
95+
96+
#[repr(C)]
97+
struct Struct {
98+
a: u8,
99+
// _pad: [MaybeUninit<u8>; 3]
100+
b: u32,
101+
c: u16,
102+
d: u8,
103+
// _pad: [MaybeUninit<u8>; 1]
104+
}
105+
106+
fn main() {}

0 commit comments

Comments
 (0)