Skip to content
Draft
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 compiler/rustc_mir_build/src/builder/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1775,7 +1775,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
unwind: UnwindAction::Continue,
},
);
self.diverge_from(block);
if false {
self.diverge_from(block);

@jdonszelmann jdonszelmann Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we no longer insert a diverge in mir when we generate an assertion (this can be scoped more in the future to just integer overflow related assertions)

View changes since the review

}

success_block
}
Expand Down
18 changes: 9 additions & 9 deletions library/core/src/num/imp/overflow_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,54 @@

#[cold]
#[track_caller]
pub(in crate::num) const fn add() -> ! {
pub(in crate::num) const fn add() -> () {

@jdonszelmann jdonszelmann Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

functions in the standard library may return unit

View changes since the review

panic!("attempt to add with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn sub() -> ! {
pub(in crate::num) const fn sub() -> () {
panic!("attempt to subtract with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn mul() -> ! {
pub(in crate::num) const fn mul() -> () {
panic!("attempt to multiply with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn div() -> ! {
pub(in crate::num) const fn div() -> () {
panic!("attempt to divide with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn rem() -> ! {
pub(in crate::num) const fn rem() -> () {
panic!("attempt to calculate the remainder with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn neg() -> ! {
pub(in crate::num) const fn neg() -> () {
panic!("attempt to negate with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn shr() -> ! {
pub(in crate::num) const fn shr() -> () {
panic!("attempt to shift right with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn shl() -> ! {
pub(in crate::num) const fn shl() -> () {
panic!("attempt to shift left with overflow")
}

#[cold]
#[track_caller]
pub(in crate::num) const fn cast_integer() -> ! {
pub(in crate::num) const fn cast_integer() -> () {
panic!("attempt to cast integer with overflow")
}
41 changes: 28 additions & 13 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,10 @@ macro_rules! int_impl {
pub const fn strict_cast_unsigned(self) -> $UnsignedT {
match self.checked_cast_unsigned() {
Some(n) => n,
None => imp::overflow_panic::cast_integer(),
None => {
imp::overflow_panic::cast_integer();
0

@jdonszelmann jdonszelmann Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returns default values. highly dubious to do this in the strict integer operations, just want to see what it's gaining us. The final version probably won't do this in strict ops

View changes since the review

}
}
}

Expand Down Expand Up @@ -621,7 +624,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_add(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_add(rhs);
if b { imp::overflow_panic::add() } else { a }
if b { imp::overflow_panic::add() }
a
}

/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
Expand Down Expand Up @@ -711,7 +715,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_add_unsigned(self, rhs: $UnsignedT) -> Self {
let (a, b) = self.overflowing_add_unsigned(rhs);
if b { imp::overflow_panic::add() } else { a }
if b { imp::overflow_panic::add() }
a
}

/// Checked integer subtraction. Computes `self - rhs`, returning `None` if
Expand Down Expand Up @@ -761,7 +766,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_sub(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_sub(rhs);
if b { imp::overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() }
a
}

/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
Expand Down Expand Up @@ -851,7 +857,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_sub_unsigned(self, rhs: $UnsignedT) -> Self {
let (a, b) = self.overflowing_sub_unsigned(rhs);
if b { imp::overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() }
a
}

/// Checked integer multiplication. Computes `self * rhs`, returning `None` if
Expand Down Expand Up @@ -901,7 +908,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_mul(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_mul(rhs);
if b { imp::overflow_panic::mul() } else { a }
if b { imp::overflow_panic::mul() }
a
}

/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
Expand Down Expand Up @@ -1008,7 +1016,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_div(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_div(rhs);
if b { imp::overflow_panic::div() } else { a }
if b { imp::overflow_panic::div() }
a
}

/// Checked Euclidean division. Computes `self.div_euclid(rhs)`,
Expand Down Expand Up @@ -1075,7 +1084,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_div_euclid(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_div_euclid(rhs);
if b { imp::overflow_panic::div() } else { a }
if b { imp::overflow_panic::div() }
a
}

/// Checked integer division without remainder. Computes `self / rhs`,
Expand Down Expand Up @@ -1247,7 +1257,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_rem(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_rem(rhs);
if b { imp::overflow_panic::rem() } else { a }
if b { imp::overflow_panic::rem() }
a
}

/// Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None`
Expand Down Expand Up @@ -1313,7 +1324,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_rem_euclid(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_rem_euclid(rhs);
if b { imp::overflow_panic::rem() } else { a }
if b { imp::overflow_panic::rem() }
a
}

/// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
Expand Down Expand Up @@ -1391,7 +1403,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_neg(self) -> Self {
let (a, b) = self.overflowing_neg();
if b { imp::overflow_panic::neg() } else { a }
if b { imp::overflow_panic::neg() }
a
}

/// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
Expand Down Expand Up @@ -1447,7 +1460,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_shl(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shl(rhs);
if b { imp::overflow_panic::shl() } else { a }
if b { imp::overflow_panic::shl() }
a
}

/// Unchecked shift left. Computes `self << rhs`, assuming that
Expand Down Expand Up @@ -1626,7 +1640,8 @@ macro_rules! int_impl {
#[track_caller]
pub const fn strict_shr(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shr(rhs);
if b { imp::overflow_panic::shr() } else { a }
if b { imp::overflow_panic::shr() }
a
}

/// Unchecked shift right. Computes `self >> rhs`, assuming that
Expand Down
29 changes: 20 additions & 9 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,10 @@ macro_rules! uint_impl {
pub const fn strict_cast_signed(self) -> $SignedT {
match self.checked_cast_signed() {
Some(n) => n,
None => imp::overflow_panic::cast_integer(),
None => {
imp::overflow_panic::cast_integer();
<$SignedT>::MAX
}
}
}

Expand Down Expand Up @@ -929,7 +932,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_add(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_add(rhs);
if b { imp::overflow_panic::add() } else { a }
if b { imp::overflow_panic::add() }
a
}

/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
Expand Down Expand Up @@ -1024,7 +1028,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_add_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_add_signed(rhs);
if b { imp::overflow_panic::add() } else { a }
if b { imp::overflow_panic::add(); }
a
}

/// Checked integer subtraction. Computes `self - rhs`, returning
Expand Down Expand Up @@ -1083,7 +1088,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_sub(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_sub(rhs);
if b { imp::overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() };
a
}

/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
Expand Down Expand Up @@ -1208,7 +1214,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_sub_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_sub_signed(rhs);
if b { imp::overflow_panic::sub() } else { a }
if b { imp::overflow_panic::sub() }
a
}

#[doc = concat!(
Expand Down Expand Up @@ -1317,7 +1324,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_mul(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_mul(rhs);
if b { imp::overflow_panic::mul() } else { a }
if b { imp::overflow_panic::mul() }
a
}

/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
Expand Down Expand Up @@ -1954,7 +1962,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_neg(self) -> Self {
let (a, b) = self.overflowing_neg();
if b { imp::overflow_panic::neg() } else { a }
if b { imp::overflow_panic::neg() }
a
}

/// Checked shift left. Computes `self << rhs`, returning `None`
Expand Down Expand Up @@ -2010,7 +2019,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_shl(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shl(rhs);
if b { imp::overflow_panic::shl() } else { a }
if b { imp::overflow_panic::shl() }
a
}

/// Unchecked shift left. Computes `self << rhs`, assuming that
Expand Down Expand Up @@ -2195,7 +2205,8 @@ macro_rules! uint_impl {
#[track_caller]
pub const fn strict_shr(self, rhs: u32) -> Self {
let (a, b) = self.overflowing_shr(rhs);
if b { imp::overflow_panic::shr() } else { a }
if b { imp::overflow_panic::shr() }
a
}

/// Unchecked shift right. Computes `self >> rhs`, assuming that
Expand Down
32 changes: 16 additions & 16 deletions library/core/src/panicking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ pub const fn panic(expr: &'static str) -> ! {
// This is especially important when this code is called often (e.g., with -Coverflow-checks) for
// reducing binary size impact.
macro_rules! panic_const {
($($lang:ident = $message:expr,)+) => {
($($lang:ident = $message:expr $(; -> $ret: ty)?,)+) => {
$(
/// This is a panic called with a message that's a result of a MIR-produced Assert.
//
Expand All @@ -170,7 +170,7 @@ macro_rules! panic_const {
#[track_caller]
#[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
#[lang = stringify!($lang)]
pub const fn $lang() -> ! {
pub const fn $lang() $(-> $ret)? {
// See the comment in `panic(&'static str)` for why we use `Arguments::from_str` here.
panic_fmt(fmt::Arguments::from_str($message));
}
Expand All @@ -193,24 +193,24 @@ pub mod panic_const {
panic_const_neg_overflow = "attempt to negate with overflow",
panic_const_shr_overflow = "attempt to shift right with overflow",
panic_const_shl_overflow = "attempt to shift left with overflow",

@jdonszelmann jdonszelmann Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overflow related panic handlers no longer return never, unit instead

View changes since the review

panic_const_div_by_zero = "attempt to divide by zero",
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero",
panic_const_coroutine_resumed = "coroutine resumed after completion",
panic_const_async_fn_resumed = "`async fn` resumed after completion",
panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion",
panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion",
panic_const_coroutine_resumed_panic = "coroutine resumed after panicking",
panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking",
panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking",
panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking",
panic_const_div_by_zero = "attempt to divide by zero"; -> !,
panic_const_rem_by_zero = "attempt to calculate the remainder with a divisor of zero"; -> !,
panic_const_coroutine_resumed = "coroutine resumed after completion"; -> !,
panic_const_async_fn_resumed = "`async fn` resumed after completion"; -> !,
panic_const_async_gen_fn_resumed = "`async gen fn` resumed after completion"; -> !,
panic_const_gen_fn_none = "`gen fn` should just keep returning `None` after completion"; -> !,
panic_const_coroutine_resumed_panic = "coroutine resumed after panicking"; -> !,
panic_const_async_fn_resumed_panic = "`async fn` resumed after panicking"; -> !,
panic_const_async_gen_fn_resumed_panic = "`async gen fn` resumed after panicking"; -> !,
panic_const_gen_fn_none_panic = "`gen fn` should just keep returning `None` after panicking"; -> !,
}
// Separated panic constants list for async drop feature
// (May be joined when the corresponding lang items will be in the bootstrap)
panic_const! {
panic_const_coroutine_resumed_drop = "coroutine resumed after async drop",
panic_const_async_fn_resumed_drop = "`async fn` resumed after async drop",
panic_const_async_gen_fn_resumed_drop = "`async gen fn` resumed after async drop",
panic_const_gen_fn_none_drop = "`gen fn` resumed after async drop",
panic_const_coroutine_resumed_drop = "coroutine resumed after async drop"; -> !,
panic_const_async_fn_resumed_drop = "`async fn` resumed after async drop"; -> !,
panic_const_async_gen_fn_resumed_drop = "`async gen fn` resumed after async drop"; -> !,
panic_const_gen_fn_none_drop = "`gen fn` resumed after async drop"; -> !,
}
}

Expand Down
1 change: 0 additions & 1 deletion tests/codegen-llvm/overflow-checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ pub unsafe fn add(a: u8, b: u8) -> u8 {
// CHECK: add i8 %b, %a
// DEBUG: icmp ult i8 [[zero:[^,]+]], %a
// DEBUG: call core::num::imp::overflow_panic::add
// DEBUG: unreachable

@jdonszelmann jdonszelmann Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was our one test checking this, even with overflow checks we won't emit unreachable anymore now :)

View changes since the review

// NOCHECKS-NOT: unreachable
// NOCHECKS: ret i8 %0
overflow_checks_add::add(a, b)
Expand Down
Loading