Skip to content

Commit 0a0f341

Browse files
committed
Auto merge of rust-lang#120594 - saethlin:delayed-debug-asserts, r=<try>
Toggle assert_unsafe_precondition in codegen instead of expansion r? `@ghost` rust-lang#120539 (comment)
2 parents 4e3eed4 + 0fdbf3c commit 0a0f341

File tree

34 files changed

+288
-500
lines changed

34 files changed

+288
-500
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,14 @@ fn codegen_regular_intrinsic_call<'tcx>(
438438
fx.bcx.ins().trap(TrapCode::User(0));
439439
return;
440440
}
441+
sym::debug_assertions => {
442+
let bool_layout = fx.layout_of(fx.tcx.types.bool);
443+
let val = CValue::by_val(
444+
fx.bcx.ins().iconst(types::I8, fx.tcx.sess.opts.debug_assertions as i64),
445+
bool_layout,
446+
);
447+
ret.write_cvalue(fx, val);
448+
}
441449
sym::likely | sym::unlikely => {
442450
intrinsic_args!(fx, args => (a); intrinsic);
443451

compiler/rustc_codegen_ssa/src/mir/block.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
676676
instance: Option<Instance<'tcx>>,
677677
source_info: mir::SourceInfo,
678678
target: Option<mir::BasicBlock>,
679-
unwind: mir::UnwindAction,
680679
mergeable_succ: bool,
681680
) -> Option<MergingSucc> {
682681
// Emit a panic or a no-op for `assert_*` intrinsics.
@@ -715,17 +714,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
715714
common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind);
716715

717716
// Codegen the actual panic invoke/call.
718-
helper.do_call(
717+
let merging_succ = helper.do_call(
719718
self,
720719
bx,
721720
fn_abi,
722721
llfn,
723722
&[msg.0, msg.1],
724-
target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
725-
unwind,
723+
None,
724+
mir::UnwindAction::Unreachable,
726725
&[],
727-
mergeable_succ,
728-
)
726+
false,
727+
);
728+
assert_eq!(merging_succ, MergingSucc::False);
729+
merging_succ
729730
} else {
730731
// a NOP
731732
let target = target.unwrap();
@@ -809,7 +810,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
809810
instance,
810811
source_info,
811812
target,
812-
unwind,
813813
mergeable_succ,
814814
) {
815815
return merging_succ;

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
8484
return;
8585
}
8686

87+
sym::debug_assertions => bx.const_bool(bx.tcx().sess.opts.debug_assertions),
8788
sym::va_start => bx.va_start(args[0].immediate()),
8889
sym::va_end => bx.va_end(args[0].immediate()),
8990
sym::size_of_val => {

compiler/rustc_const_eval/src/const_eval/machine.rs

+5
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
536536
// (We know the value here in the machine of course, but this is the runtime of that code,
537537
// not the optimization stage.)
538538
sym::is_val_statically_known => ecx.write_scalar(Scalar::from_bool(false), dest)?,
539+
540+
sym::debug_assertions => {
541+
ecx.write_scalar(Scalar::from_bool(ecx.tcx.sess.opts.debug_assertions), dest)?
542+
}
543+
539544
_ => {
540545
throw_unsup_format!(
541546
"intrinsic `{intrinsic_name}` is not supported at compile-time"

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
112112
| sym::forget
113113
| sym::black_box
114114
| sym::variant_count
115-
| sym::ptr_mask => hir::Unsafety::Normal,
115+
| sym::ptr_mask
116+
| sym::debug_assertions => hir::Unsafety::Normal,
116117
_ => hir::Unsafety::Unsafe,
117118
};
118119

@@ -461,6 +462,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
461462
(0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
462463
}
463464

465+
sym::debug_assertions => (0, Vec::new(), tcx.types.bool),
466+
464467
other => {
465468
tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
466469
return;

library/core/src/intrinsics.rs

+39-18
Original file line numberDiff line numberDiff line change
@@ -2569,6 +2569,12 @@ extern "rust-intrinsic" {
25692569
#[rustc_nounwind]
25702570
#[cfg(not(bootstrap))]
25712571
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
2572+
2573+
#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
2574+
#[rustc_safe_intrinsic]
2575+
#[rustc_nounwind]
2576+
#[cfg(not(bootstrap))]
2577+
pub(crate) fn debug_assertions() -> bool;
25722578
}
25732579

25742580
// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
@@ -2604,27 +2610,37 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
26042610
///
26052611
/// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make
26062612
/// the occasional mistake, and this check should help them figure things out.
2607-
#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn
2613+
#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn
26082614
macro_rules! assert_unsafe_precondition {
26092615
($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => {
2610-
if cfg!(debug_assertions) {
2611-
// allow non_snake_case to allow capturing const generics
2612-
#[allow(non_snake_case)]
2613-
#[inline(always)]
2614-
fn runtime$(<$($tt)*>)?($($i:$ty),*) {
2615-
if !$e {
2616-
// don't unwind to reduce impact on code size
2617-
::core::panicking::panic_nounwind(
2618-
concat!("unsafe precondition(s) violated: ", $name)
2619-
);
2620-
}
2616+
{
2617+
// allow non_snake_case to allow capturing const generics
2618+
#[allow(non_snake_case)]
2619+
#[inline(always)]
2620+
fn runtime$(<$($tt)*>)?($($i:$ty),*) {
2621+
#[cfg(miri)]
2622+
return;
2623+
if !$e {
2624+
// don't unwind to reduce impact on code size
2625+
::core::panicking::panic_nounwind(
2626+
concat!("unsafe precondition(s) violated: ", $name)
2627+
);
26212628
}
2622-
#[allow(non_snake_case)]
2623-
#[inline]
2624-
const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
2629+
}
2630+
#[allow(non_snake_case)]
2631+
#[inline]
2632+
const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
26252633

2634+
#[cfg(bootstrap)]
2635+
if cfg!(debug_assertions) {
26262636
::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
26272637
}
2638+
2639+
#[cfg(not(bootstrap))]
2640+
if ::core::intrinsics::debug_assertions() {
2641+
::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
2642+
}
2643+
}
26282644
};
26292645
}
26302646
pub(crate) use assert_unsafe_precondition;
@@ -2633,19 +2649,20 @@ pub(crate) use assert_unsafe_precondition;
26332649
/// `align_of::<T>()`.
26342650
#[inline]
26352651
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
2636-
!ptr.is_null() && ptr.is_aligned()
2652+
((ptr.addr() & const { crate::mem::align_of::<T>() - 1 }) == 0) & (ptr.addr() != 0)
26372653
}
26382654

2655+
/*
26392656
/// Checks whether an allocation of `len` instances of `T` exceeds
26402657
/// the maximum allowed allocation size.
26412658
#[inline]
26422659
pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
2643-
let max_len = const {
2660+
len <= const {
26442661
let size = crate::mem::size_of::<T>();
26452662
if size == 0 { usize::MAX } else { isize::MAX as usize / size }
26462663
};
2647-
len <= max_len
26482664
}
2665+
*/
26492666

26502667
/// Checks whether the regions of memory starting at `src` and `dst` of size
26512668
/// `count * size_of::<T>()` do *not* overlap.
@@ -2763,6 +2780,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
27632780
// SAFETY: the safety contract for `copy_nonoverlapping` must be
27642781
// upheld by the caller.
27652782
unsafe {
2783+
/*
27662784
assert_unsafe_precondition!(
27672785
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
27682786
and the specified memory ranges do not overlap",
@@ -2771,6 +2789,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
27712789
&& is_aligned_and_not_null(dst)
27722790
&& is_nonoverlapping(src, dst, count)
27732791
);
2792+
*/
27742793
copy_nonoverlapping(src, dst, count)
27752794
}
27762795
}
@@ -2858,11 +2877,13 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
28582877

28592878
// SAFETY: the safety contract for `copy` must be upheld by the caller.
28602879
unsafe {
2880+
/*
28612881
assert_unsafe_precondition!(
28622882
"ptr::copy requires that both pointer arguments are aligned and non-null",
28632883
[T](src: *const T, dst: *mut T) =>
28642884
is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
28652885
);
2886+
*/
28662887
copy(src, dst, count)
28672888
}
28682889
}

library/core/src/ptr/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1208,10 +1208,12 @@ pub const unsafe fn read<T>(src: *const T) -> T {
12081208

12091209
// SAFETY: the caller must guarantee that `src` is valid for reads.
12101210
unsafe {
1211+
/*
12111212
assert_unsafe_precondition!(
12121213
"ptr::read requires that the pointer argument is aligned and non-null",
12131214
[T](src: *const T) => is_aligned_and_not_null(src)
12141215
);
1216+
*/
12151217
crate::intrinsics::read_via_copy(src)
12161218
}
12171219
}
@@ -1408,10 +1410,12 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
14081410
// `dst` cannot overlap `src` because the caller has mutable access
14091411
// to `dst` while `src` is owned by this function.
14101412
unsafe {
1413+
/*
14111414
assert_unsafe_precondition!(
14121415
"ptr::write requires that the pointer argument is aligned and non-null",
14131416
[T](dst: *mut T) => is_aligned_and_not_null(dst)
14141417
);
1418+
*/
14151419
intrinsics::write_via_move(dst, src)
14161420
}
14171421
}

library/core/src/ptr/non_null.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::cmp::Ordering;
22
use crate::fmt;
33
use crate::hash;
44
use crate::intrinsics;
5-
use crate::intrinsics::assert_unsafe_precondition;
5+
//use crate::intrinsics::assert_unsafe_precondition;
66
use crate::marker::Unsize;
77
use crate::mem::SizedTypeProperties;
88
use crate::mem::{self, MaybeUninit};
@@ -218,7 +218,7 @@ impl<T: ?Sized> NonNull<T> {
218218
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
219219
// SAFETY: the caller must guarantee that `ptr` is non-null.
220220
unsafe {
221-
assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null());
221+
//assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null());
222222
NonNull { pointer: ptr as _ }
223223
}
224224
}

library/core/src/slice/raw.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! Free functions to create `&[T]` and `&mut [T]`.
22
33
use crate::array;
4+
/*
45
use crate::intrinsics::{
56
assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size,
67
};
8+
*/
79
use crate::ops::Range;
810
use crate::ptr;
911

@@ -94,11 +96,13 @@ use crate::ptr;
9496
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
9597
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
9698
unsafe {
99+
/*
97100
assert_unsafe_precondition!(
98101
"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`",
99102
[T](data: *const T, len: usize) => is_aligned_and_not_null(data)
100103
&& is_valid_allocation_size::<T>(len)
101104
);
105+
*/
102106
&*ptr::slice_from_raw_parts(data, len)
103107
}
104108
}
@@ -141,11 +145,13 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
141145
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
142146
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
143147
unsafe {
148+
/*
144149
assert_unsafe_precondition!(
145150
"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`",
146151
[T](data: *mut T, len: usize) => is_aligned_and_not_null(data)
147152
&& is_valid_allocation_size::<T>(len)
148153
);
154+
*/
149155
&mut *ptr::slice_from_raw_parts_mut(data, len)
150156
}
151157
}

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff

-25
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,7 @@
2525
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
2626
debug ptr => _6;
2727
let mut _8: *const [bool; 0];
28-
let mut _9: *mut [bool; 0];
2928
scope 12 {
30-
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
31-
debug ptr => _9;
32-
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
33-
debug self => _9;
34-
let mut _10: *mut u8;
35-
scope 15 {
36-
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
37-
debug ptr => _10;
38-
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
39-
debug self => _10;
40-
scope 18 {
41-
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
42-
debug self => _10;
43-
}
44-
}
45-
}
46-
}
47-
}
48-
}
49-
}
5029
}
5130
}
5231
}
@@ -74,12 +53,8 @@
7453
_6 = const {0x1 as *mut [bool; 0]};
7554
StorageDead(_7);
7655
StorageLive(_8);
77-
StorageLive(_9);
78-
StorageLive(_10);
7956
_8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
8057
_5 = NonNull::<[bool; 0]> { pointer: _8 };
81-
StorageDead(_10);
82-
StorageDead(_9);
8358
StorageDead(_8);
8459
StorageDead(_6);
8560
_4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };

tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff

-25
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,7 @@
2525
scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
2626
debug ptr => _6;
2727
let mut _8: *const [bool; 0];
28-
let mut _9: *mut [bool; 0];
2928
scope 12 {
30-
scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
31-
debug ptr => _9;
32-
scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
33-
debug self => _9;
34-
let mut _10: *mut u8;
35-
scope 15 {
36-
scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
37-
debug ptr => _10;
38-
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
39-
debug self => _10;
40-
scope 18 {
41-
scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
42-
debug self => _10;
43-
}
44-
}
45-
}
46-
}
47-
}
48-
}
49-
}
5029
}
5130
}
5231
}
@@ -74,12 +53,8 @@
7453
_6 = const {0x1 as *mut [bool; 0]};
7554
StorageDead(_7);
7655
StorageLive(_8);
77-
StorageLive(_9);
78-
StorageLive(_10);
7956
_8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
8057
_5 = NonNull::<[bool; 0]> { pointer: _8 };
81-
StorageDead(_10);
82-
StorageDead(_9);
8358
StorageDead(_8);
8459
StorageDead(_6);
8560
_4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };

0 commit comments

Comments
 (0)