]> git.lizzy.rs Git - rust.git/commitdiff
Inherit overflow checks for sum and product
authorSteven Fackler <sfackler@gmail.com>
Sat, 10 Sep 2016 03:39:49 +0000 (20:39 -0700)
committerSteven Fackler <sfackler@gmail.com>
Sat, 10 Sep 2016 17:06:33 +0000 (10:06 -0700)
src/libcore/iter/iterator.rs
src/libcore/iter/traits.rs
src/test/run-pass/iter-sum-overflow-debug.rs [new file with mode: 0644]
src/test/run-pass/iter-sum-overflow-ndebug.rs [new file with mode: 0644]

index 6b616f8018156bf8e5e217d46de70b4223d109e8..0e74bbe9c2600fa5e698f0a1ae32866018834163 100644 (file)
@@ -1867,7 +1867,8 @@ fn cycle(self) -> Cycle<Self> where Self: Sized + Clone {
     /// # Panics
     ///
     /// When calling `sum` and a primitive integer type is being returned, this
-    /// method will panic if the computation overflows.
+    /// method will panic if the computation overflows and debug assertions are
+    /// enabled.
     ///
     /// # Examples
     ///
@@ -1894,7 +1895,8 @@ fn sum<S>(self) -> S
     /// # Panics
     ///
     /// When calling `product` and a primitive integer type is being returned,
-    /// this method will panic if the computation overflows.
+    /// method will panic if the computation overflows and debug assertions are
+    /// enabled.
     ///
     /// # Examples
     ///
index 59e23c4d960567d6af82c729eada07b6becd1c14..563fb213d376365e342584f604aad31adaaca54a 100644 (file)
@@ -7,6 +7,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
+use ops::{Mul, Add};
 
 /// Conversion from an `Iterator`.
 ///
@@ -581,41 +582,35 @@ pub trait Product<A = Self>: Sized {
     fn product<I: Iterator<Item=A>>(iter: I) -> Self;
 }
 
+// NB: explicitly use Add and Mul here to inherit overflow checks
 macro_rules! integer_sum_product {
     ($($a:ident)*) => ($(
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl Sum for $a {
+            #[rustc_inherit_overflow_checks]
             fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
-                iter.fold(0, |a, b| {
-                    a.checked_add(b).expect("overflow in sum")
-                })
+                iter.fold(0, Add::add)
             }
         }
 
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl Product for $a {
             fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
-                iter.fold(1, |a, b| {
-                    a.checked_mul(b).expect("overflow in product")
-                })
+                iter.fold(1, Mul::mul)
             }
         }
 
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl<'a> Sum<&'a $a> for $a {
             fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
-                iter.fold(0, |a, b| {
-                    a.checked_add(*b).expect("overflow in sum")
-                })
+                iter.cloned().fold(0, Add::add)
             }
         }
 
         #[stable(feature = "iter_arith_traits", since = "1.12.0")]
         impl<'a> Product<&'a $a> for $a {
             fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
-                iter.fold(1, |a, b| {
-                    a.checked_mul(*b).expect("overflow in product")
-                })
+                iter.cloned().fold(1, Mul::mul)
             }
         }
     )*)
diff --git a/src/test/run-pass/iter-sum-overflow-debug.rs b/src/test/run-pass/iter-sum-overflow-debug.rs
new file mode 100644 (file)
index 0000000..6c07afb
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C debug_assertions=yes
+
+use std::panic;
+
+fn main() {
+    let r = panic::catch_unwind(|| {
+        [1, i32::max_value()].iter().sum::<i32>();
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        [2, i32::max_value()].iter().product::<i32>();
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        [1, i32::max_value()].iter().cloned().sum::<i32>();
+    });
+    assert!(r.is_err());
+
+    let r = panic::catch_unwind(|| {
+        [2, i32::max_value()].iter().cloned().product::<i32>();
+    });
+    assert!(r.is_err());
+}
diff --git a/src/test/run-pass/iter-sum-overflow-ndebug.rs b/src/test/run-pass/iter-sum-overflow-ndebug.rs
new file mode 100644 (file)
index 0000000..65ac1ef
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C debug_assertions=no
+
+fn main() {
+    assert_eq!([1i32, i32::max_value()].iter().sum::<i32>(),
+               1i32.wrapping_add(i32::max_value()));
+    assert_eq!([2i32, i32::max_value()].iter().product::<i32>(),
+               2i32.wrapping_mul(i32::max_value()));
+
+    assert_eq!([1i32, i32::max_value()].iter().cloned().sum::<i32>(),
+               1i32.wrapping_add(i32::max_value()));
+    assert_eq!([2i32, i32::max_value()].iter().cloned().product::<i32>(),
+               2i32.wrapping_mul(i32::max_value()));
+}