Skip to content

Commit c94c007

Browse files
author
Lukas Markeffsky
committed
const align
1 parent b0728ab commit c94c007

File tree

6 files changed

+65
-56
lines changed

6 files changed

+65
-56
lines changed

library/core/src/intrinsics.rs

+18-17
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
use crate::marker::DiscriminantKind;
5858
use crate::marker::Tuple;
5959
use crate::mem;
60+
use crate::panic::debug_assert_nounwind;
6061

6162
pub mod mir;
6263

@@ -2500,13 +2501,15 @@ pub(crate) use assert_unsafe_precondition;
25002501

25012502
/// Checks whether `ptr` is properly aligned with respect to
25022503
/// `align_of::<T>()`.
2503-
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
2504+
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
2505+
pub(crate) const fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
25042506
!ptr.is_null() && ptr.is_aligned()
25052507
}
25062508

25072509
/// Checks whether an allocation of `len` instances of `T` exceeds
25082510
/// the maximum allowed allocation size.
2509-
pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
2511+
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
2512+
pub(crate) const fn is_valid_allocation_size<T>(len: usize) -> bool {
25102513
let max_len = const {
25112514
let size = crate::mem::size_of::<T>();
25122515
if size == 0 { usize::MAX } else { isize::MAX as usize / size }
@@ -2707,22 +2710,21 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
27072710
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
27082711
#[inline]
27092712
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2713+
#[rustc_allow_const_fn_unstable(core_panic)]
27102714
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
27112715
extern "rust-intrinsic" {
27122716
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
27132717
#[rustc_nounwind]
27142718
fn copy<T>(src: *const T, dst: *mut T, count: usize);
27152719
}
27162720

2721+
debug_assert_nounwind!(
2722+
is_aligned_and_not_null(src) && is_aligned_and_not_null(dst),
2723+
"ptr::copy requires that both pointer arguments are aligned aligned and non-null",
2724+
);
2725+
27172726
// SAFETY: the safety contract for `copy` must be upheld by the caller.
2718-
unsafe {
2719-
assert_unsafe_precondition!(
2720-
"ptr::copy requires that both pointer arguments are aligned aligned and non-null",
2721-
[T](src: *const T, dst: *mut T) =>
2722-
is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
2723-
);
2724-
copy(src, dst, count)
2725-
}
2727+
unsafe { copy(src, dst, count) }
27262728
}
27272729

27282730
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
@@ -2787,12 +2789,11 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
27872789
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
27882790
}
27892791

2792+
debug_assert_nounwind!(
2793+
is_aligned_and_not_null(dst),
2794+
"ptr::write_bytes requires that the destination pointer is aligned and non-null",
2795+
);
2796+
27902797
// SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
2791-
unsafe {
2792-
assert_unsafe_precondition!(
2793-
"ptr::write_bytes requires that the destination pointer is aligned and non-null",
2794-
[T](dst: *mut T) => is_aligned_and_not_null(dst)
2795-
);
2796-
write_bytes(dst, val, count)
2797-
}
2798+
unsafe { write_bytes(dst, val, count) }
27982799
}

library/core/src/panicking.rs

+8
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,15 @@ pub const fn panic(expr: &'static str) -> ! {
137137
#[cfg_attr(feature = "panic_immediate_abort", inline)]
138138
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
139139
#[rustc_nounwind]
140+
const fn lang_panic_nounwind(expr: &'static str) -> ! {
141+
panic_nounwind(expr);
142+
}
143+
144+
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
145+
#[cfg_attr(feature = "panic_immediate_abort", inline)]
146+
#[rustc_nounwind]
140147
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
148+
#[track_caller]
141149
pub const fn panic_nounwind(expr: &'static str) -> ! {
142150
panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]));
143151
}

library/core/src/ptr/mod.rs

+22-20
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ use crate::hash;
374374
use crate::intrinsics::{
375375
self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping,
376376
};
377+
use crate::panic::debug_assert_nounwind;
377378

378379
use crate::mem::{self, MaybeUninit};
379380

@@ -1161,13 +1162,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
11611162
// Future enhancements to MIR optimizations might well allow this to return
11621163
// to the previous implementation, rather than using an intrinsic.
11631164

1165+
debug_assert_nounwind!(
1166+
is_aligned_and_not_null(src),
1167+
"ptr::read requires that the pointer argument is aligned and non-null",
1168+
);
1169+
11641170
// SAFETY: the caller must guarantee that `src` is valid for reads.
11651171
unsafe {
1166-
assert_unsafe_precondition!(
1167-
"ptr::read requires that the pointer argument is aligned and non-null",
1168-
[T](src: *const T) => is_aligned_and_not_null(src)
1169-
);
1170-
11711172
#[cfg(bootstrap)]
11721173
{
11731174
// We are calling the intrinsics directly to avoid function calls in the
@@ -1375,14 +1376,15 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
13751376
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
13761377
}
13771378

1379+
debug_assert_nounwind!(
1380+
is_aligned_and_not_null(dst),
1381+
"ptr::write requires that the pointer argument is aligned and non-null",
1382+
);
1383+
13781384
// SAFETY: the caller must guarantee that `dst` is valid for writes.
13791385
// `dst` cannot overlap `src` because the caller has mutable access
13801386
// to `dst` while `src` is owned by this function.
13811387
unsafe {
1382-
assert_unsafe_precondition!(
1383-
"ptr::write requires that the pointer argument is aligned and non-null",
1384-
[T](dst: *mut T) => is_aligned_and_not_null(dst)
1385-
);
13861388
copy_nonoverlapping(&src as *const T, dst, 1);
13871389
intrinsics::forget(src);
13881390
}
@@ -1544,14 +1546,13 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
15441546
#[stable(feature = "volatile", since = "1.9.0")]
15451547
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
15461548
pub unsafe fn read_volatile<T>(src: *const T) -> T {
1549+
debug_assert_nounwind!(
1550+
is_aligned_and_not_null(src),
1551+
"ptr::read_volatile requires that the pointer argument is aligned and non-null",
1552+
);
1553+
15471554
// SAFETY: the caller must uphold the safety contract for `volatile_load`.
1548-
unsafe {
1549-
assert_unsafe_precondition!(
1550-
"ptr::read_volatile requires that the pointer argument is aligned and non-null",
1551-
[T](src: *const T) => is_aligned_and_not_null(src)
1552-
);
1553-
intrinsics::volatile_load(src)
1554-
}
1555+
unsafe { intrinsics::volatile_load(src) }
15551556
}
15561557

15571558
/// Performs a volatile write of a memory location with the given value without
@@ -1618,12 +1619,13 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
16181619
#[stable(feature = "volatile", since = "1.9.0")]
16191620
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
16201621
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
1622+
debug_assert_nounwind!(
1623+
is_aligned_and_not_null(dst),
1624+
"ptr::write_volatile requires that the pointer argument is aligned and non-null",
1625+
);
1626+
16211627
// SAFETY: the caller must uphold the safety contract for `volatile_store`.
16221628
unsafe {
1623-
assert_unsafe_precondition!(
1624-
"ptr::write_volatile requires that the pointer argument is aligned and non-null",
1625-
[T](dst: *mut T) => is_aligned_and_not_null(dst)
1626-
);
16271629
intrinsics::volatile_store(dst, src);
16281630
}
16291631
}

library/core/src/slice/raw.rs

+15-19
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
//! Free functions to create `&[T]` and `&mut [T]`.
22
33
use crate::array;
4-
use crate::intrinsics::{
5-
assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size,
6-
};
4+
use crate::intrinsics::{is_aligned_and_not_null, is_valid_allocation_size};
75
use crate::ops::Range;
6+
use crate::panic::debug_assert_nounwind;
87
use crate::ptr;
98

109
/// Forms a slice from a pointer and a length.
@@ -89,16 +88,15 @@ use crate::ptr;
8988
#[stable(feature = "rust1", since = "1.0.0")]
9089
#[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
9190
#[must_use]
91+
#[rustc_allow_const_fn_unstable(core_panic)]
9292
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
93+
debug_assert_nounwind!(
94+
is_aligned_and_not_null(data) && is_valid_allocation_size::<T>(len),
95+
"slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
96+
);
97+
9398
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
94-
unsafe {
95-
assert_unsafe_precondition!(
96-
"slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
97-
[T](data: *const T, len: usize) => is_aligned_and_not_null(data)
98-
&& is_valid_allocation_size::<T>(len)
99-
);
100-
&*ptr::slice_from_raw_parts(data, len)
101-
}
99+
unsafe { &*ptr::slice_from_raw_parts(data, len) }
102100
}
103101

104102
/// Performs the same functionality as [`from_raw_parts`], except that a
@@ -135,15 +133,13 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
135133
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
136134
#[must_use]
137135
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
136+
debug_assert_nounwind!(
137+
is_aligned_and_not_null(data) && is_valid_allocation_size::<T>(len),
138+
"slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
139+
);
140+
138141
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
139-
unsafe {
140-
assert_unsafe_precondition!(
141-
"slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
142-
[T](data: *mut T, len: usize) => is_aligned_and_not_null(data)
143-
&& is_valid_allocation_size::<T>(len)
144-
);
145-
&mut *ptr::slice_from_raw_parts_mut(data, len)
146-
}
142+
unsafe { &mut *ptr::slice_from_raw_parts_mut(data, len) }
147143
}
148144

149145
/// Converts a reference to T into a slice of length 1 (without copying).

tests/ui/const-ptr/forbidden_slices.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-debug
12
// Strip out raw byte dumps to make comparison platform-independent:
23
// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
34
// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP"

tests/ui/consts/const-eval/ub-ref-ptr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// ignore-tidy-linelength
2+
// ignore-debug
23
// Strip out raw byte dumps to make comparison platform-independent:
34
// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
45
// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP"

0 commit comments

Comments
 (0)