Skip to content

Commit b531364

Browse files
authored
Rollup merge of #90377 - WaffleLapkin:const_slice_from_raw_parts, r=oli-obk
Make `core::slice::from_raw_parts[_mut]` const Responses to #90012 seem to allow ``@rust-lang/wg-const-eval`` to decide on use of `const_eval_select`, so we can make `core::slice::from_raw_parts[_mut]` const :) --- This PR marks the following APIs as const: ```rust // core::slice pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]; pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T]; ``` --- Resolves #90011 r? ``@oli-obk``
2 parents a213740 + afaa54a commit b531364

File tree

2 files changed

+43
-14
lines changed

2 files changed

+43
-14
lines changed

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
#![feature(const_caller_location)]
106106
#![feature(const_cell_into_inner)]
107107
#![feature(const_discriminant)]
108+
#![cfg_attr(not(bootstrap), feature(const_eval_select))]
108109
#![feature(const_float_bits_conv)]
109110
#![feature(const_float_classify)]
110111
#![feature(const_fmt_arguments_new)]

library/core/src/slice/raw.rs

+42-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//! Free functions to create `&[T]` and `&mut [T]`.
22
33
use crate::array;
4-
use crate::intrinsics::is_aligned_and_not_null;
5-
use crate::mem;
64
use crate::ptr;
75

86
/// Forms a slice from a pointer and a length.
@@ -85,12 +83,10 @@ use crate::ptr;
8583
/// [`NonNull::dangling()`]: ptr::NonNull::dangling
8684
#[inline]
8785
#[stable(feature = "rust1", since = "1.0.0")]
88-
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
89-
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
90-
debug_assert!(
91-
mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
92-
"attempt to create slice covering at least half the address space"
93-
);
86+
#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
87+
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
88+
debug_check_data_len(data, len);
89+
9490
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
9591
unsafe { &*ptr::slice_from_raw_parts(data, len) }
9692
}
@@ -126,16 +122,48 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
126122
/// [`NonNull::dangling()`]: ptr::NonNull::dangling
127123
#[inline]
128124
#[stable(feature = "rust1", since = "1.0.0")]
129-
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
130-
debug_assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
131-
debug_assert!(
132-
mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
133-
"attempt to create slice covering at least half the address space"
134-
);
125+
#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
126+
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
127+
debug_check_data_len(data as _, len);
128+
135129
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
136130
unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
137131
}
138132

133+
// In debug builds checks that `data` pointer is aligned and non-null and that slice with given `len` would cover less than half the address space
134+
#[cfg(all(not(bootstrap), debug_assertions))]
135+
#[unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
136+
#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
137+
const fn debug_check_data_len<T>(data: *const T, len: usize) {
138+
fn rt_check<T>(data: *const T) {
139+
use crate::intrinsics::is_aligned_and_not_null;
140+
141+
assert!(is_aligned_and_not_null(data), "attempt to create unaligned or null slice");
142+
}
143+
144+
const fn noop<T>(_: *const T) {}
145+
146+
// SAFETY:
147+
//
148+
// `rt_check` is just a debug assert to hint users that they are causing UB,
149+
// it is not required for safety (the safety must be guatanteed by
150+
// the `from_raw_parts[_mut]` caller).
151+
//
152+
// Since the checks are not required, we ignore them in CTFE as they can't
153+
// be done there (alignment does not make much sense there).
154+
unsafe {
155+
crate::intrinsics::const_eval_select((data,), noop, rt_check);
156+
}
157+
158+
assert!(
159+
crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize,
160+
"attempt to create slice covering at least half the address space"
161+
);
162+
}
163+
164+
#[cfg(not(all(not(bootstrap), debug_assertions)))]
165+
const fn debug_check_data_len<T>(_data: *const T, _len: usize) {}
166+
139167
/// Converts a reference to T into a slice of length 1 (without copying).
140168
#[stable(feature = "from_ref", since = "1.28.0")]
141169
#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")]

0 commit comments

Comments
 (0)