Skip to content
Open
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
63 changes: 63 additions & 0 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,39 @@ macro_rules! int_impl {
}
}

/// Unchecked integer division. Computes `self / rhs`, assuming `rhs != 0` and
/// overflow cannot occur.
///
/// Calling `x.unchecked_div(y)` is semantically equivalent to calling
/// `x.`[`checked_div`]`(y).`[`unwrap_unchecked`]`()`.
///
/// # Safety
///
/// This results in undefined behavior when `rhs == 0` or
#[doc = concat!("(`self == ", stringify!($SelfT), "::MIN` and `rhs == -1`),")]
/// i.e. when [`checked_div`] would return `None`.
///
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
#[doc = concat!("[`checked_div`]: ", stringify!($SelfT), "::checked_div")]
#[doc = concat!("[`wrapping_div`]: ", stringify!($SelfT), "::wrapping_div")]
Copy link
Member

Choose a reason for hiding this comment

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

This link too.

#[unstable(feature = "unchecked_div_rem", issue = "136716")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_div(self, rhs: Self) -> Self {
assert_unsafe_precondition!(
check_language_ub,
concat!(stringify!($SelfT), "::unchecked_div cannot overflow or divide by zero"),
(
lhs: $SelfT = self,
rhs: $SelfT = rhs
) => rhs != 0 && !lhs.overflowing_div(rhs).1,
);

// SAFETY: this is guaranteed to be safe by the caller.
unsafe { intrinsics::unchecked_div(self, rhs) }
}

/// Strict integer division. Computes `self / rhs`, panicking
/// if overflow occurred.
///
Expand Down Expand Up @@ -1044,6 +1077,36 @@ macro_rules! int_impl {
}
}

/// Unchecked integer remainder. Computes `self % rhs`, assuming `rhs != 0`
/// and overflow cannot occur.
///
/// # Safety
///
/// This results in undefined behavior when `rhs == 0` or
#[doc = concat!("(`self == ", stringify!($SelfT), "::MIN` and `rhs == -1`),")]
/// i.e. when [`checked_rem`] would return `None`.
///
#[doc = concat!("[`checked_rem`]: ", stringify!($SelfT), "::checked_rem")]
#[unstable(feature = "unchecked_div_rem", issue = "136716")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_rem(self, rhs: Self) -> Self {
assert_unsafe_precondition!(
check_language_ub,
concat!(stringify!($SelfT), "::unchecked_rem cannot overflow or divide by zero"),
(
lhs: $SelfT = self,
rhs: $SelfT = rhs
) => rhs != 0 && !lhs.overflowing_rem(rhs).1,
);

// SAFETY: this is guaranteed to be safe by the caller.
unsafe {
intrinsics::unchecked_rem(self, rhs)
}
}

/// Strict integer remainder. Computes `self % rhs`, panicking if
/// the division results in overflow.
///
Expand Down
57 changes: 57 additions & 0 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,36 @@ macro_rules! uint_impl {
}
}

/// Unchecked integer division. Computes `self / rhs`, assuming `rhs` is not zero.
///
/// Calling `x.unchecked_div(y)` is semantically equivalent to calling
/// `x.`[`checked_div`]`(y).`[`unwrap_unchecked`]`()`.
///
/// # Safety
///
/// This results in undefined behavior when `rhs == 0`,
/// i.e. when [`checked_div`] would return `None`.
///
/// [`unwrap_unchecked`]: option/enum.Option.html#method.unwrap_unchecked
#[doc = concat!("[`checked_div`]: ", stringify!($SelfT), "::checked_div")]
#[doc = concat!("[`wrapping_div`]: ", stringify!($SelfT), "::wrapping_div")]
Copy link
Member

Choose a reason for hiding this comment

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

This link seems unused, or am I missing something?

#[unstable(feature = "unchecked_div_rem", issue = "136716")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_div(self, rhs: Self) -> Self {
assert_unsafe_precondition!(
check_language_ub,
concat!(stringify!($SelfT), "::unchecked_div cannot divide by zero"),
(
rhs: $SelfT = rhs
) => rhs != 0,
);

// SAFETY: this is guaranteed to be safe by the caller.
unsafe { intrinsics::unchecked_div(self, rhs) }
}

/// Strict integer division. Computes `self / rhs`.
///
/// Strict division on unsigned types is just normal division. There's no
Expand Down Expand Up @@ -1136,6 +1166,33 @@ macro_rules! uint_impl {
}
}

/// Unchecked integer remainder. Computes `self % rhs`, assuming `rhs` is not zero.
///
/// # Safety
///
/// This results in undefined behavior when `rhs == 0`,
/// i.e. when [`checked_rem`] would return `None`.
///
#[doc = concat!("[`checked_rem`]: ", stringify!($SelfT), "::checked_rem")]
#[unstable(feature = "unchecked_div_rem", issue = "136716")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_rem(self, rhs: Self) -> Self {
assert_unsafe_precondition!(
check_language_ub,
concat!(stringify!($SelfT), "::unchecked_rem cannot divide by zero"),
(
rhs: $SelfT = rhs
) => rhs != 0,
);

// SAFETY: this is guaranteed to be safe by the caller.
unsafe {
intrinsics::unchecked_rem(self, rhs)
}
}

/// Strict integer remainder. Computes `self % rhs`.
///
/// Strict remainder calculation on unsigned types is just the regular
Expand Down
Loading