Skip to content

Commit 83d48cd

Browse files
authored
Unrolled build for rust-lang#120888
Rollup merge of rust-lang#120888 - saethlin:unsafe-precondition-cleanup, r=RalfJung assert_unsafe_precondition cleanup I moved the polymorphic `is_nonoverlapping` into the `Cell` function that uses it and renamed `intrinsics::is_nonoverlapping_mono` to just `intrinsics::is_nonoverlapping`. We now also have some docs for `intrinsics::debug_assertions`. r? RalfJung
2 parents 520b0b2 + f0de100 commit 83d48cd

File tree

3 files changed

+34
-38
lines changed

3 files changed

+34
-38
lines changed

library/core/src/cell.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,9 @@
237237

238238
use crate::cmp::Ordering;
239239
use crate::fmt::{self, Debug, Display};
240-
use crate::intrinsics::is_nonoverlapping;
240+
use crate::intrinsics;
241241
use crate::marker::{PhantomData, Unsize};
242-
use crate::mem;
242+
use crate::mem::{self, size_of};
243243
use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn};
244244
use crate::ptr::{self, NonNull};
245245

@@ -435,11 +435,15 @@ impl<T> Cell<T> {
435435
#[inline]
436436
#[stable(feature = "move_cell", since = "1.17.0")]
437437
pub fn swap(&self, other: &Self) {
438+
fn is_nonoverlapping<T>(src: *const T, dst: *const T) -> bool {
439+
intrinsics::is_nonoverlapping(src.cast(), dst.cast(), size_of::<T>(), 1)
440+
}
441+
438442
if ptr::eq(self, other) {
439443
// Swapping wouldn't change anything.
440444
return;
441445
}
442-
if !is_nonoverlapping(self, other, 1) {
446+
if !is_nonoverlapping(self, other) {
443447
// See <https://github.com/rust-lang/rust/issues/80778> for why we need to stop here.
444448
panic!("`Cell::swap` on overlapping non-identical `Cell`s");
445449
}

library/core/src/intrinsics.rs

+25-33
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
use crate::marker::DiscriminantKind;
5858
use crate::marker::Tuple;
59-
use crate::mem::{self, align_of};
59+
use crate::mem::align_of;
6060

6161
pub mod mir;
6262
pub mod simd;
@@ -1027,7 +1027,7 @@ extern "rust-intrinsic" {
10271027

10281028
/// The size of the referenced value in bytes.
10291029
///
1030-
/// The stabilized version of this intrinsic is [`mem::size_of_val`].
1030+
/// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
10311031
#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
10321032
#[rustc_nounwind]
10331033
pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
@@ -1107,7 +1107,7 @@ extern "rust-intrinsic" {
11071107

11081108
/// Moves a value out of scope without running drop glue.
11091109
///
1110-
/// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
1110+
/// This exists solely for [`crate::mem::forget_unsized`]; normal `forget` uses
11111111
/// `ManuallyDrop` instead.
11121112
///
11131113
/// Note that, unlike most intrinsics, this is safe to call;
@@ -1233,7 +1233,7 @@ extern "rust-intrinsic" {
12331233
/// Depending on what the code is doing, the following alternatives are preferable to
12341234
/// pointer-to-integer transmutation:
12351235
/// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a
1236-
/// type for that buffer, it can use [`MaybeUninit`][mem::MaybeUninit].
1236+
/// type for that buffer, it can use [`MaybeUninit`][crate::mem::MaybeUninit].
12371237
/// - If the code actually wants to work on the address the pointer points to, it can use `as`
12381238
/// casts or [`ptr.addr()`][pointer::addr].
12391239
///
@@ -2317,7 +2317,7 @@ extern "rust-intrinsic" {
23172317
/// Therefore, implementations must not require the user to uphold
23182318
/// any safety invariants.
23192319
///
2320-
/// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
2320+
/// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`].
23212321
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
23222322
#[rustc_safe_intrinsic]
23232323
#[rustc_nounwind]
@@ -2569,6 +2569,19 @@ extern "rust-intrinsic" {
25692569
#[rustc_nounwind]
25702570
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
25712571

2572+
/// Returns the value of `cfg!(debug_assertions)`, but after monomorphization instead of in
2573+
/// macro expansion.
2574+
///
2575+
/// This always returns `false` in const eval and Miri. The interpreter provides better
2576+
/// diagnostics than the checks that this is used to implement. However, this means
2577+
/// you should only be using this intrinsic to guard requirements that, if violated,
2578+
/// immediately lead to UB. Otherwise, const-eval and Miri will miss out on those
2579+
/// checks entirely.
2580+
///
2581+
/// Since this is evaluated after monomorphization, branching on this value can be used to
2582+
/// implement debug assertions that are included in the precompiled standard library, but can
2583+
/// be optimized out by builds that monomorphize the standard library code with debug
2584+
/// assertions disabled. This intrinsic is primarily used by [`assert_unsafe_precondition`].
25722585
#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
25732586
#[rustc_safe_intrinsic]
25742587
#[cfg(not(bootstrap))]
@@ -2597,7 +2610,7 @@ pub(crate) const fn debug_assertions() -> bool {
25972610
/// These checks are behind a condition which is evaluated at codegen time, not expansion time like
25982611
/// [`debug_assert`]. This means that a standard library built with optimizations and debug
25992612
/// assertions disabled will have these checks optimized out of its monomorphizations, but if a
2600-
/// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of
2613+
/// caller of the standard library has debug assertions enabled and monomorphizes an expansion of
26012614
/// this macro, that monomorphization will contain the check.
26022615
///
26032616
/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and
@@ -2606,8 +2619,8 @@ pub(crate) const fn debug_assertions() -> bool {
26062619
/// combination of properties ensures that the code for the checks is only compiled once, and has a
26072620
/// minimal impact on the caller's code size.
26082621
///
2609-
/// Caller should also introducing any other `let` bindings or any code outside this macro in order
2610-
/// to call it. Since the precompiled standard library is built with full debuginfo and these
2622+
/// Callers should also avoid introducing any other `let` bindings or any code outside this macro in
2623+
/// order to call it. Since the precompiled standard library is built with full debuginfo and these
26112624
/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough
26122625
/// debuginfo to have a measurable compile-time impact on debug builds.
26132626
///
@@ -2659,33 +2672,12 @@ pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool {
26592672
len <= max_len
26602673
}
26612674

2662-
pub(crate) fn is_nonoverlapping_mono(
2663-
src: *const (),
2664-
dst: *const (),
2665-
size: usize,
2666-
count: usize,
2667-
) -> bool {
2668-
let src_usize = src.addr();
2669-
let dst_usize = dst.addr();
2670-
let Some(size) = size.checked_mul(count) else {
2671-
crate::panicking::panic_nounwind(
2672-
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
2673-
)
2674-
};
2675-
let diff = src_usize.abs_diff(dst_usize);
2676-
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
2677-
// they do not overlap.
2678-
diff >= size
2679-
}
2680-
26812675
/// Checks whether the regions of memory starting at `src` and `dst` of size
2682-
/// `count * size_of::<T>()` do *not* overlap.
2683-
#[inline]
2684-
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
2676+
/// `count * size` do *not* overlap.
2677+
pub(crate) fn is_nonoverlapping(src: *const (), dst: *const (), size: usize, count: usize) -> bool {
26852678
let src_usize = src.addr();
26862679
let dst_usize = dst.addr();
2687-
let Some(size) = mem::size_of::<T>().checked_mul(count) else {
2688-
// Use panic_nounwind instead of Option::expect, so that this function is nounwind.
2680+
let Some(size) = size.checked_mul(count) else {
26892681
crate::panicking::panic_nounwind(
26902682
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
26912683
)
@@ -2809,7 +2801,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
28092801
) =>
28102802
is_aligned_and_not_null(src, align)
28112803
&& is_aligned_and_not_null(dst, align)
2812-
&& is_nonoverlapping_mono(src, dst, size, count)
2804+
&& is_nonoverlapping(src, dst, size, count)
28132805
);
28142806
copy_nonoverlapping(src, dst, count)
28152807
}

library/core/src/ptr/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ use crate::cmp::Ordering;
383383
use crate::fmt;
384384
use crate::hash;
385385
use crate::intrinsics::{
386-
self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping_mono,
386+
self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping,
387387
};
388388
use crate::marker::FnPtr;
389389

@@ -978,7 +978,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
978978
) =>
979979
is_aligned_and_not_null(x, align)
980980
&& is_aligned_and_not_null(y, align)
981-
&& is_nonoverlapping_mono(x, y, size, count)
981+
&& is_nonoverlapping(x, y, size, count)
982982
);
983983
}
984984

0 commit comments

Comments
 (0)