Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rename debug_assert_nounwind → debug_assert_ubcheck #121583

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion library/core/src/ops/index_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ impl IndexRange {
/// - `start <= end`
#[inline]
pub const unsafe fn new_unchecked(start: usize, end: usize) -> Self {
crate::panic::debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter
// will miss out on this check.
crate::panic::debug_assert_ubcheck!(
start <= end,
"IndexRange::new_unchecked requires `start <= end`"
);
Expand Down
18 changes: 11 additions & 7 deletions library/core/src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,16 @@ pub macro unreachable_2021 {
/// checks are enabled when they are monomorphized with debug assertions enabled, and upon failure
/// a non-unwinding panic is launched so that failures cannot compromise unwind safety.
///
/// But there are many differences from `assert_unsafe_precondition!`. This macro does not use
/// `const_eval_select` internally, and therefore it is sound to call this with an expression
/// that evaluates to `false`. Also unlike `assert_unsafe_precondition!` the condition being
/// checked here is not put in an outlined function. If the check compiles to a lot of IR, this
/// can cause code bloat if the check is monomorphized many times. But it also means that the checks
/// from this macro can be deduplicated or otherwise optimized out.
/// These checks are not executed in the interpreter (const-eval and Miri), so they should only
/// check requirements that immediately lead to UB if violated (and the interpreter will then show a
/// nice diagnostic for that UB).
///
/// But there are many differences from `assert_unsafe_precondition!`. Most importantly, the
/// condition being checked here is not put in an outlined function. If the check compiles to a lot
/// of IR, this can cause code bloat if the check is monomorphized many times. But it also means
/// that the checks from this macro can be deduplicated or otherwise optimized out.
/// This also does not use `const_eval_select` so making sure that the code has UB if the condition
/// is violated is not a soundness concern, but as noted above it is still a correctness concern.
///
/// In general, this macro should be used to check all public-facing preconditions. But some
/// preconditions may be called too often or instantiated too often to make the overhead of the
Expand All @@ -159,7 +163,7 @@ pub macro unreachable_2021 {
#[unstable(feature = "panic_internals", issue = "none")]
#[allow_internal_unstable(panic_internals, delayed_debug_assertions)]
#[rustc_macro_transparency = "semitransparent"]
pub macro debug_assert_nounwind {
pub macro debug_assert_ubcheck {
($cond:expr $(,)?) => {
if $crate::intrinsics::debug_assertions() {
if !$cond {
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/ptr/alignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl Alignment {
#[inline]
pub const unsafe fn new_unchecked(align: usize) -> Self {
#[cfg(debug_assertions)]
crate::panic::debug_assert_nounwind!(
crate::panic::debug_assert_ubcheck!(
align.is_power_of_two(),
"Alignment::new_unchecked requires a power of two"
);
Expand Down
24 changes: 17 additions & 7 deletions library/core/src/slice/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::intrinsics::const_eval_select;
use crate::intrinsics::unchecked_sub;
use crate::ops;
use crate::panic::debug_assert_nounwind;
use crate::panic::debug_assert_ubcheck;
use crate::ptr;

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -225,7 +225,7 @@ unsafe impl<T> SliceIndex<[T]> for usize {

#[inline]
unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
debug_assert_nounwind!(
debug_assert_ubcheck!(
self < slice.len(),
"slice::get_unchecked requires that the index is within the slice"
);
Expand All @@ -243,7 +243,9 @@ unsafe impl<T> SliceIndex<[T]> for usize {

#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The offset might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
self < slice.len(),
"slice::get_unchecked_mut requires that the index is within the slice"
);
Expand Down Expand Up @@ -292,7 +294,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {

#[inline]
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The end might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
self.end() <= slice.len(),
"slice::get_unchecked requires that the index is within the slice"
);
Expand All @@ -305,7 +309,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {

#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The end might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
self.end() <= slice.len(),
"slice::get_unchecked_mut requires that the index is within the slice"
);
Expand Down Expand Up @@ -362,7 +368,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {

#[inline]
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The end might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
self.end >= self.start && self.end <= slice.len(),
"slice::get_unchecked requires that the range is within the slice"
);
Expand All @@ -379,7 +387,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {

#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The end might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
self.end >= self.start && self.end <= slice.len(),
"slice::get_unchecked_mut requires that the range is within the slice"
);
Expand Down
18 changes: 12 additions & 6 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::intrinsics::exact_div;
use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZero;
use crate::ops::{Bound, OneSidedRange, Range, RangeBounds};
use crate::panic::debug_assert_nounwind;
use crate::panic::debug_assert_ubcheck;
use crate::ptr;
use crate::simd::{self, Simd};
use crate::slice;
Expand Down Expand Up @@ -945,7 +945,9 @@ impl<T> [T] {
#[unstable(feature = "slice_swap_unchecked", issue = "88539")]
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The indices might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
a < self.len() && b < self.len(),
"slice::swap_unchecked requires that the indices are within the slice"
);
Expand Down Expand Up @@ -1285,7 +1287,7 @@ impl<T> [T] {
#[inline]
#[must_use]
pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
debug_assert_nounwind!(
debug_assert_ubcheck!(
N != 0 && self.len() % N == 0,
"slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks"
);
Expand Down Expand Up @@ -1439,7 +1441,7 @@ impl<T> [T] {
#[inline]
#[must_use]
pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
debug_assert_nounwind!(
debug_assert_ubcheck!(
N != 0 && self.len() % N == 0,
"slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks"
);
Expand Down Expand Up @@ -1971,7 +1973,9 @@ impl<T> [T] {
let len = self.len();
let ptr = self.as_ptr();

debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (`mid` might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
mid <= len,
"slice::split_at_unchecked requires the index to be within the slice"
);
Expand Down Expand Up @@ -2021,7 +2025,9 @@ impl<T> [T] {
let len = self.len();
let ptr = self.as_mut_ptr();

debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (`mid`` might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
mid <= len,
"slice::split_at_mut_unchecked requires the index to be within the slice"
);
Expand Down
10 changes: 7 additions & 3 deletions library/core/src/str/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::cmp::Ordering;
use crate::ops;
use crate::panic::debug_assert_nounwind;
use crate::panic::debug_assert_ubcheck;
use crate::ptr;
use crate::slice::SliceIndex;

Expand Down Expand Up @@ -192,7 +192,9 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
let slice = slice as *const [u8];

debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The end might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
// We'd like to check that the bounds are on char boundaries,
// but there's not really a way to do so without reading
// behind the pointer, which has aliasing implications.
Expand All @@ -213,7 +215,9 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
let slice = slice as *mut [u8];

debug_assert_nounwind!(
// FIXME: violating this is not immediate language UB, so the interpreter will miss out on
// this check. (The end might be OOB of the slice but still inbounds of the allocation.)
debug_assert_ubcheck!(
self.end >= self.start && self.end <= slice.len(),
"str::get_unchecked_mut requires that the range is within the string slice"
);
Expand Down
Loading