Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 3e5570d

Browse files
committed
Auto merge of rust-lang#134938 - saethlin:include-precondition-args, r=<try>
Include arguments to the precondition check in failure messages For now, just checking if this tanks compile times or something like that. It shouldn't? I hope? r? ghost
2 parents 2061630 + 65e5e12 commit 3e5570d

File tree

3 files changed

+68
-19
lines changed

3 files changed

+68
-19
lines changed

‎library/core/src/slice/index.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Indexing implementations for `[T]`.
22
33
use crate::panic::const_panic;
4-
use crate::ub_checks::assert_unsafe_precondition;
4+
use crate::ub_checks::assert_unsafe_precondition2;
55
use crate::{ops, range};
66

77
#[stable(feature = "rust1", since = "1.0.0")]
@@ -240,10 +240,10 @@ unsafe impl<T> SliceIndex<[T]> for usize {
240240

241241
#[inline]
242242
unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
243-
assert_unsafe_precondition!(
243+
assert_unsafe_precondition2!(
244244
check_language_ub,
245-
"slice::get_unchecked requires that the index is within the slice",
246-
(this: usize = self, len: usize = slice.len()) => this < len
245+
"slice::get_unchecked requires that the index is within the slice (index:{index}, len:{len})",
246+
(index: usize = self, len: usize = slice.len()) => index < len
247247
);
248248
// SAFETY: the caller guarantees that `slice` is not dangling, so it
249249
// cannot be longer than `isize::MAX`. They also guarantee that
@@ -259,10 +259,10 @@ unsafe impl<T> SliceIndex<[T]> for usize {
259259

260260
#[inline]
261261
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
262-
assert_unsafe_precondition!(
262+
assert_unsafe_precondition2!(
263263
check_library_ub,
264-
"slice::get_unchecked_mut requires that the index is within the slice",
265-
(this: usize = self, len: usize = slice.len()) => this < len
264+
"slice::get_unchecked_mut requires that the index is within the slice (index:{index}, len:{len})",
265+
(index: usize = self, len: usize = slice.len()) => index < len
266266
);
267267
// SAFETY: see comments for `get_unchecked` above.
268268
unsafe { get_mut_noubcheck(slice, self) }
@@ -308,9 +308,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
308308

309309
#[inline]
310310
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
311-
assert_unsafe_precondition!(
311+
assert_unsafe_precondition2!(
312312
check_library_ub,
313-
"slice::get_unchecked requires that the index is within the slice",
313+
"slice::get_unchecked requires that the index is within the slice (end:{end}, len:{len})",
314314
(end: usize = self.end(), len: usize = slice.len()) => end <= len
315315
);
316316
// SAFETY: the caller guarantees that `slice` is not dangling, so it
@@ -322,9 +322,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
322322

323323
#[inline]
324324
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
325-
assert_unsafe_precondition!(
325+
assert_unsafe_precondition2!(
326326
check_library_ub,
327-
"slice::get_unchecked_mut requires that the index is within the slice",
327+
"slice::get_unchecked_mut requires that the index is within the slice (end:{end}, len:{len})",
328328
(end: usize = self.end(), len: usize = slice.len()) => end <= len
329329
);
330330

@@ -387,9 +387,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
387387

388388
#[inline]
389389
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
390-
assert_unsafe_precondition!(
390+
assert_unsafe_precondition2!(
391391
check_library_ub,
392-
"slice::get_unchecked requires that the range is within the slice",
392+
"slice::get_unchecked requires that the range is within the slice (range:{start}..{end}, len:{len})",
393393
(
394394
start: usize = self.start,
395395
end: usize = self.end,
@@ -411,9 +411,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
411411

412412
#[inline]
413413
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
414-
assert_unsafe_precondition!(
414+
assert_unsafe_precondition2!(
415415
check_library_ub,
416-
"slice::get_unchecked_mut requires that the range is within the slice",
416+
"slice::get_unchecked_mut requires that the range is within the slice (range:{start}..{end}, len:{len})",
417417
(
418418
start: usize = self.start,
419419
end: usize = self.end,

‎library/core/src/slice/raw.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ use crate::{array, ptr, ub_checks};
123123
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
124124
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
125125
unsafe {
126-
ub_checks::assert_unsafe_precondition!(
126+
ub_checks::assert_unsafe_precondition2!(
127127
check_language_ub,
128-
"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`",
128+
"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` (data:{data:?}, size:{size:?}, align:{align:?}, len:{len:?})",
129129
(
130130
data: *mut () = data as *mut (),
131131
size: usize = size_of::<T>(),
@@ -177,9 +177,9 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
177177
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
178178
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
179179
unsafe {
180-
ub_checks::assert_unsafe_precondition!(
180+
ub_checks::assert_unsafe_precondition2!(
181181
check_language_ub,
182-
"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`",
182+
"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` (data:{data:?}, size:{size:?}, align:{align:?}, len:{len:?})",
183183
(
184184
data: *mut () = data as *mut (),
185185
size: usize = size_of::<T>(),

‎library/core/src/ub_checks.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,55 @@ macro_rules! assert_unsafe_precondition {
7979
}
8080
#[unstable(feature = "ub_checks", issue = "none")]
8181
pub use assert_unsafe_precondition;
82+
83+
/// assert_unsafe_precondition, but full
84+
#[macro_export]
85+
#[unstable(feature = "ub_checks", issue = "none")]
86+
macro_rules! assert_unsafe_precondition2 {
87+
($kind:ident, $message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => {
88+
{
89+
// This check is inlineable, but not by the MIR inliner.
90+
// The reason for this is that the MIR inliner is in an exceptionally bad position
91+
// to think about whether or not to inline this. In MIR, this call is gated behind `debug_assertions`,
92+
// which will codegen to `false` in release builds. Inlining the check would be wasted work in that case and
93+
// would be bad for compile times.
94+
//
95+
// LLVM on the other hand sees the constant branch, so if it's `false`, it can immediately delete it without
96+
// inlining the check. If it's `true`, it can inline it and get significantly better performance.
97+
#[rustc_no_mir_inline]
98+
#[inline]
99+
#[rustc_nounwind]
100+
#[track_caller]
101+
#[rustc_allow_const_fn_unstable(const_eval_select)]
102+
const fn precondition_check($($name:$ty),*) {
103+
if $e { return; }
104+
crate::intrinsics::const_eval_select!(
105+
@capture { $($name: $ty),* }:
106+
if const #[track_caller] {
107+
::core::panicking::panic_nounwind(
108+
concat!("unsafe precondition(s) violated: ", $message)
109+
);
110+
} else #[track_caller] {
111+
::core::panicking::panic_nounwind_fmt(
112+
format_args!(
113+
concat!("unsafe precondition(s) violated: ", $message),
114+
$($name=$name),*
115+
),
116+
false
117+
);
118+
}
119+
)
120+
}
121+
122+
if ::core::ub_checks::$kind() {
123+
precondition_check($($arg,)*);
124+
}
125+
}
126+
};
127+
}
128+
#[unstable(feature = "ub_checks", issue = "none")]
129+
pub use assert_unsafe_precondition2;
130+
82131
/// Checking library UB is always enabled when UB-checking is done
83132
/// (and we use a reexport so that there is no unnecessary wrapper function).
84133
#[unstable(feature = "ub_checks", issue = "none")]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /