-
Notifications
You must be signed in to change notification settings - Fork 22
Closed
Labels
ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)API Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard librariesA proposal to add or alter unstable APIs in the standard libraries
Description
Proposal
Problem statement
At the moment, there are impl {Div,Rem}<NonZeroX> for X
which use the fact that the division by a non-zero value are always infallible.
Yet there seem to be no corresponding {Div,Rem}Assign
implementations. While the lhs %= rhs
and lhs/= rhs
can be described in user code with lhs = lhs / rhs
and lhs = lhs % rhs
respectively, there seems to be no reason to not implement the corresponding traits on numeric types themselves.
Motivating examples or use cases
Simply,
let mut b = 123u8;
let a = NonZeroU8::new(1).unwrap();
b = b / a;
compiles; but
let mut b = 123u8;
let a = NonZeroU8::new(1).unwrap();
b /= a;
does not.
Solution sketch
The implementation (tested against master
) adds the following into core::num::nonzero::nonzero_integer_signedness_dependent_impls
:
#[stable(feature = "nonzero_div2", since = "CURRENT_RUSTC_VERSION")]
impl DivAssign<$Ty> for $Int {
/// This operation rounds towards zero,
/// truncating any fractional part of the exact result, and cannot panic.
#[inline]
fn div_assign(&mut self, other: $Ty) {
*self = *self / other;
}
}
#[stable(feature = "nonzero_div2", since = "CURRENT_RUSTC_VERSION")]
impl RemAssign<$Ty> for $Int {
/// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
#[inline]
fn rem_assign(&mut self, other: $Ty) {
*self = *self % other;
}
}
Diff
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 9e34c0d240d..61257cd71e3 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -5,7 +5,7 @@
use crate::hash::{Hash, Hasher};
use crate::intrinsics;
use crate::marker::StructuralPartialEq;
-use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem};
+use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
use crate::str::FromStr;
use super::from_str_radix;
@@ -800,6 +800,16 @@ fn div(self, other: $Ty) -> $Int {
}
}
+ #[stable(feature = "nonzero_div2", since = "CURRENT_RUSTC_VERSION")]
+ impl DivAssign<$Ty> for $Int {
+ /// This operation rounds towards zero,
+ /// truncating any fractional part of the exact result, and cannot panic.
+ #[inline]
+ fn div_assign(&mut self, other: $Ty) {
+ *self = *self / other;
+ }
+ }
+
#[stable(feature = "nonzero_div", since = "1.51.0")]
impl Rem<$Ty> for $Int {
type Output = $Int;
@@ -812,6 +822,15 @@ fn rem(self, other: $Ty) -> $Int {
unsafe { intrinsics::unchecked_rem(self, other.get()) }
}
}
+
+ #[stable(feature = "nonzero_div2", since = "CURRENT_RUSTC_VERSION")]
+ impl RemAssign<$Ty> for $Int {
+ /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic.
+ #[inline]
+ fn rem_assign(&mut self, other: $Ty) {
+ *self = *self % other;
+ }
+ }
};
// Impls for signed nonzero types only.
I've used the synthetic nonzero_div2
feature for these and, IMO, they may be an insta-stable API.
Alternatives
- Status quo: these trait implementations are not obligatory and thus we can just not ignore them, but I don't see any reason for it, while implementing them seems to be a consistency enhancement.
kennytm and joshtriplett
Metadata
Metadata
Assignees
Labels
ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)API Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard librariesA proposal to add or alter unstable APIs in the standard libraries