Skip to content

Commit 0310c45

Browse files
committed
Clean up library/ and infer unwind: unreachable
1 parent 3404820 commit 0310c45

File tree

34 files changed

+740
-1087
lines changed

34 files changed

+740
-1087
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

-1
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,6 @@ 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-
540539
_ => {
541540
throw_unsup_format!(
542541
"intrinsic `{intrinsic_name}` is not supported at compile-time"

compiler/rustc_mir_transform/src/instsimplify.rs

+25
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
33
use crate::simplify::simplify_duplicate_switch_targets;
44
use rustc_middle::mir::*;
5+
use rustc_middle::ty::layout;
56
use rustc_middle::ty::layout::ValidityRequirement;
67
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
78
use rustc_span::symbol::Symbol;
89
use rustc_target::abi::FieldIdx;
10+
use rustc_target::spec::abi::Abi;
911

1012
pub struct InstSimplify;
1113

@@ -38,6 +40,7 @@ impl<'tcx> MirPass<'tcx> for InstSimplify {
3840
block.terminator.as_mut().unwrap(),
3941
&mut block.statements,
4042
);
43+
ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap());
4144
simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
4245
}
4346
}
@@ -252,6 +255,28 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
252255
terminator.kind = TerminatorKind::Goto { target: destination_block };
253256
}
254257

258+
fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
259+
let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else {
260+
return;
261+
};
262+
263+
let Some((def_id, _)) = func.const_fn_def() else {
264+
return;
265+
};
266+
267+
let body_ty = self.tcx.type_of(def_id).skip_binder();
268+
let body_abi = match body_ty.kind() {
269+
ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(),
270+
ty::Closure(..) => Abi::RustCall,
271+
ty::Coroutine(..) => Abi::Rust,
272+
_ => bug!("unexpected body ty: {:?}", body_ty),
273+
};
274+
275+
if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) {
276+
*unwind = UnwindAction::Unreachable;
277+
}
278+
}
279+
255280
fn simplify_intrinsic_assert(
256281
&self,
257282
terminator: &mut Terminator<'tcx>,

library/core/src/char/convert.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
2727
unsafe {
2828
assert_unsafe_precondition!(
2929
"invalid value for `char`",
30-
(i: u32) => char_try_from_u32(i).is_ok()
30+
(i => i:u32) => char_try_from_u32(i).is_ok()
3131
);
3232
transmute(i)
3333
}

library/core/src/hint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) {
148148
unsafe {
149149
intrinsics::assert_unsafe_precondition!(
150150
"hint::assert_unchecked must never be called when the condition is false",
151-
(cond: bool) => cond,
151+
(cond => cond: bool) => cond,
152152
);
153153
crate::intrinsics::assume(cond);
154154
}

library/core/src/intrinsics.rs

+60-87
Original file line numberDiff line numberDiff line change
@@ -2617,22 +2617,22 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
26172617
/// the occasional mistake, and this check should help them figure things out.
26182618
#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn
26192619
macro_rules! assert_unsafe_precondition {
2620-
($name:expr, ($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => {
2620+
($message:expr, ($($arg:expr => $name:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => {
26212621
{
26222622
#[inline(never)]
2623-
fn precondition_check($($i:$ty),*) {
2623+
#[rustc_nounwind]
2624+
fn precondition_check($($name:$ty),*) {
26242625
if !$e {
26252626
::core::panicking::panic_nounwind(
2626-
concat!("unsafe precondition(s) violated: ", $name)
2627+
concat!("unsafe precondition(s) violated: ", $message)
26272628
);
26282629
}
26292630
}
2630-
#[allow(non_snake_case)]
26312631
#[inline]
26322632
const fn comptime($(_:$ty),*) {}
26332633

26342634
if ::core::intrinsics::debug_assertions() {
2635-
::core::intrinsics::const_eval_select(($($i,)*), comptime, precondition_check);
2635+
::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check);
26362636
}
26372637
}
26382638
};
@@ -2643,7 +2643,32 @@ pub(crate) use assert_unsafe_precondition;
26432643
/// `align_of::<T>()`.
26442644
#[inline]
26452645
pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool {
2646-
ptr.is_aligned_to(align) && !ptr.is_null()
2646+
!ptr.is_null() && ptr.is_aligned_to(align)
2647+
}
2648+
2649+
#[inline]
2650+
pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool {
2651+
let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };
2652+
len <= max_len
2653+
}
2654+
2655+
pub(crate) fn is_nonoverlapping_mono(
2656+
src: *const (),
2657+
dst: *const (),
2658+
size: usize,
2659+
count: usize,
2660+
) -> bool {
2661+
let src_usize = src.addr();
2662+
let dst_usize = dst.addr();
2663+
let Some(size) = size.checked_mul(count) else {
2664+
crate::panicking::panic_nounwind(
2665+
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
2666+
)
2667+
};
2668+
let diff = src_usize.abs_diff(dst_usize);
2669+
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
2670+
// they do not overlap.
2671+
diff >= size
26472672
}
26482673

26492674
/// Checks whether the regions of memory starting at `src` and `dst` of size
@@ -2755,70 +2780,31 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
27552780
#[inline(always)]
27562781
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
27572782
#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
2758-
#[rustc_allow_const_fn_unstable(const_eval_select)]
27592783
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
27602784
extern "rust-intrinsic" {
27612785
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
27622786
#[rustc_nounwind]
27632787
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
27642788
}
27652789

2766-
const fn compiletime(_: *const (), _: *mut (), _: usize, _: usize, _: usize) {}
2767-
27682790
// SAFETY: the safety contract for `copy_nonoverlapping` must be
27692791
// upheld by the caller.
27702792
unsafe {
2771-
if crate::intrinsics::debug_assertions() {
2772-
const_eval_select(
2773-
(
2774-
src as *const (),
2775-
dst as *mut (),
2776-
crate::mem::size_of::<T>(),
2777-
crate::mem::align_of::<T>(),
2778-
count,
2779-
),
2780-
compiletime,
2781-
check_aligned_nonoverlapping,
2782-
);
2783-
}
2784-
copy_nonoverlapping(src, dst, count)
2785-
}
2786-
}
2787-
2788-
#[inline(never)]
2789-
pub(crate) fn check_aligned_nonoverlapping(
2790-
src: *const (),
2791-
dst: *mut (),
2792-
size: usize,
2793-
align: usize,
2794-
count: usize,
2795-
) {
2796-
if src.is_null() || dst.is_null() {
2797-
crate::panicking::panic_nounwind(
2798-
"ptr::copy_nonoverlapping requires that both pointer arguments are non-null",
2799-
);
2800-
}
2801-
if !src.is_aligned_to(align) || !dst.is_aligned_to(align) {
2802-
crate::panicking::panic_nounwind(
2803-
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned",
2804-
);
2805-
}
2806-
let src_usize = src.addr();
2807-
let dst_usize = dst.addr();
2808-
let Some(size) = size.checked_mul(count) else {
2809-
crate::panicking::panic_nounwind(
2810-
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
2811-
)
2812-
};
2813-
let diff = src_usize.abs_diff(dst_usize);
2814-
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
2815-
// they do not overlap.
2816-
let is_nonoverlapping = diff >= size;
2817-
2818-
if !is_nonoverlapping {
2819-
crate::panicking::panic_nounwind(
2820-
"ptr::copy_nonoverlapping requires the specified memory ranges do not overlap",
2793+
assert_unsafe_precondition!(
2794+
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
2795+
and the specified memory ranges do not overlap",
2796+
(
2797+
src as *const () => src: *const (),
2798+
dst as *mut () => dst: *mut (),
2799+
size_of::<T>() => size: usize,
2800+
align_of::<T>() => align: usize,
2801+
count => count: usize,
2802+
) =>
2803+
is_aligned_and_not_null(src, align)
2804+
&& is_aligned_and_not_null(dst, align)
2805+
&& is_nonoverlapping_mono(src, dst, size, count)
28212806
);
2807+
copy_nonoverlapping(src, dst, count)
28222808
}
28232809
}
28242810

@@ -2896,41 +2882,27 @@ pub(crate) fn check_aligned_nonoverlapping(
28962882
#[inline(always)]
28972883
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
28982884
#[rustc_diagnostic_item = "ptr_copy"]
2899-
#[rustc_allow_const_fn_unstable(const_eval_select)]
29002885
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
29012886
extern "rust-intrinsic" {
29022887
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
29032888
#[rustc_nounwind]
29042889
fn copy<T>(src: *const T, dst: *mut T, count: usize);
29052890
}
29062891

2907-
const fn compiletime(_: *const (), _: *mut (), _: usize) {}
2908-
29092892
// SAFETY: the safety contract for `copy` must be upheld by the caller.
29102893
unsafe {
2911-
if crate::intrinsics::debug_assertions() {
2912-
const_eval_select(
2913-
(src as *const (), dst as *mut (), align_of::<T>()),
2914-
compiletime,
2915-
check_valid_copy,
2916-
);
2917-
}
2918-
copy(src, dst, count)
2919-
}
2920-
}
2921-
2922-
#[inline(never)]
2923-
#[rustc_nounwind]
2924-
fn check_valid_copy(src: *const (), dst: *mut (), align: usize) {
2925-
if src.is_null() || dst.is_null() {
2926-
crate::panicking::panic_nounwind(
2927-
"ptr::copy requires that both pointer arguments are non-null",
2928-
);
2929-
}
2930-
if !src.is_aligned_to(align) || !dst.is_aligned_to(align) {
2931-
crate::panicking::panic_nounwind(
2932-
"ptr::copy requires that both pointer arguments are aligned",
2894+
assert_unsafe_precondition!(
2895+
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
2896+
and the specified memory ranges do not overlap",
2897+
(
2898+
src as *const () => src: *const (),
2899+
dst as *mut () => dst: *mut (),
2900+
align_of::<T>() => align: usize,
2901+
) =>
2902+
is_aligned_and_not_null(src, align)
2903+
&& is_aligned_and_not_null(dst, align)
29332904
);
2905+
copy(src, dst, count)
29342906
}
29352907
}
29362908

@@ -2997,13 +2969,14 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
29972969
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
29982970
}
29992971

3000-
let addr = dst as *const ();
3001-
let align = align_of::<T>();
30022972
// SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
30032973
unsafe {
30042974
assert_unsafe_precondition!(
30052975
"ptr::write_bytes requires that the destination pointer is aligned and non-null",
3006-
(addr: *const (), align: usize) => is_aligned_and_not_null(addr, align)
2976+
(
2977+
dst as *const () => addr: *const (),
2978+
align_of::<T>() => align: usize
2979+
) => is_aligned_and_not_null(addr, align)
30072980
);
30082981
write_bytes(dst, val, count)
30092982
}

library/core/src/num/nonzero.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,9 @@ macro_rules! nonzero_integer {
190190
pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self {
191191
// SAFETY: Self is repr(transparent), and the value is assumed to be non-zero.
192192
unsafe {
193-
let n_alias = &mut *n;
194193
core::intrinsics::assert_unsafe_precondition!(
195194
concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"),
196-
(n_alias: &mut $Int) => *n_alias != 0
195+
(&mut *n => n: &mut $Int) => *n != 0
197196
);
198197
&mut *(n as *mut $Int as *mut Self)
199198
}

library/core/src/ptr/const_ptr.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -806,14 +806,15 @@ impl<T: ?Sized> *const T {
806806
where
807807
T: Sized,
808808
{
809-
let this = self as *const ();
810-
let arg = origin as *const ();
811809
// SAFETY: The comparison has no side-effects, and the intrinsic
812810
// does this check internally in the CTFE implementation.
813811
unsafe {
814812
assert_unsafe_precondition!(
815813
"ptr::sub_ptr requires `self >= origin`",
816-
(this: *const (), arg: *const ()) => this >= arg
814+
(
815+
self as *const () => this: *const (),
816+
origin as *const () => origin: *const (),
817+
) => this >= origin
817818
)
818819
};
819820

0 commit comments

Comments
 (0)