Skip to content

Commit c55cda3

Browse files
branpkmbrubeck
authored andcommitted
Make assignment operators panic safe
1 parent e8fe06a commit c55cda3

File tree

2 files changed

+20
-10
lines changed

2 files changed

+20
-10
lines changed

src/lib.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,7 @@ impl<T: Float + AddAssign> AddAssign for NotNan<T> {
377377
/// Panics if the provided value is NaN.
378378
impl<T: Float + AddAssign> AddAssign<T> for NotNan<T> {
379379
fn add_assign(&mut self, other: T) {
380-
self.0 += other;
381-
assert!(!self.0.is_nan(), "Addition resulted in NaN");
380+
*self = *self + other;
382381
}
383382
}
384383

@@ -425,8 +424,7 @@ impl<T: Float + SubAssign> SubAssign for NotNan<T> {
425424
/// Panics if the provided value is NaN or the computation results in NaN
426425
impl<T: Float + SubAssign> SubAssign<T> for NotNan<T> {
427426
fn sub_assign(&mut self, other: T) {
428-
self.0 -= other;
429-
assert!(!self.0.is_nan(), "Subtraction resulted in NaN");
427+
*self = *self - other;
430428
}
431429
}
432430

@@ -460,8 +458,7 @@ impl<T: Float + MulAssign> MulAssign for NotNan<T> {
460458
/// Panics if the provided value is NaN.
461459
impl<T: Float + MulAssign> MulAssign<T> for NotNan<T> {
462460
fn mul_assign(&mut self, other: T) {
463-
self.0 *= other;
464-
assert!(!self.0.is_nan(), "Multiplication resulted in NaN");
461+
*self = *self * other;
465462
}
466463
}
467464

@@ -507,8 +504,7 @@ impl<T: Float + DivAssign> DivAssign for NotNan<T> {
507504
/// Panics if the provided value is NaN or the computation results in NaN
508505
impl<T: Float + DivAssign> DivAssign<T> for NotNan<T> {
509506
fn div_assign(&mut self, other: T) {
510-
self.0 /= other;
511-
assert!(!self.0.is_nan(), "Division resulted in NaN");
507+
*self = *self / other;
512508
}
513509
}
514510

@@ -542,8 +538,7 @@ impl<T: Float + RemAssign> RemAssign for NotNan<T> {
542538
/// Panics if the provided value is NaN or the computation results in NaN
543539
impl<T: Float + RemAssign> RemAssign<T> for NotNan<T> {
544540
fn rem_assign(&mut self, other: T) {
545-
self.0 %= other;
546-
assert!(!self.0.is_nan(), "Rem resulted in NaN");
541+
*self = *self % other;
547542
}
548543
}
549544

tests/test.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,3 +590,18 @@ fn not_nan_usage_in_const_context() {
590590
const A: NotNan<f32> = unsafe { NotNan::unchecked_new(111f32) };
591591
assert_eq!(A, NotNan::new(111f32).unwrap());
592592
}
593+
594+
#[test]
595+
fn not_nan_panic_safety() {
596+
let catch_op = |mut num, op: fn(&mut NotNan<_>)| {
597+
let mut num_ref = panic::AssertUnwindSafe(&mut num);
598+
let _ = panic::catch_unwind(move || op(*num_ref));
599+
num
600+
};
601+
602+
assert!(!catch_op(not_nan(f32::INFINITY), |a| *a += f32::NEG_INFINITY).is_nan());
603+
assert!(!catch_op(not_nan(f32::INFINITY), |a| *a -= f32::INFINITY).is_nan());
604+
assert!(!catch_op(not_nan(0.0), |a| *a *= f32::INFINITY).is_nan());
605+
assert!(!catch_op(not_nan(0.0), |a| *a /= 0.0).is_nan());
606+
assert!(!catch_op(not_nan(0.0), |a| *a %= 0.0).is_nan());
607+
}

0 commit comments

Comments
 (0)