From 63fecad2e7c1f58e962a100d4159ddd47ebc627f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 9 Sep 2016 20:39:49 -0700 Subject: [PATCH 1/2] Inherit overflow checks for sum and product --- src/libcore/iter/iterator.rs | 6 ++-- src/libcore/iter/traits.rs | 19 ++++------ src/test/run-pass/iter-sum-overflow-debug.rs | 35 +++++++++++++++++++ src/test/run-pass/iter-sum-overflow-ndebug.rs | 23 ++++++++++++ 4 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 src/test/run-pass/iter-sum-overflow-debug.rs create mode 100644 src/test/run-pass/iter-sum-overflow-ndebug.rs diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 6b616f8018156..0e74bbe9c2600 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1867,7 +1867,8 @@ pub trait Iterator { /// # 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 @@ pub trait Iterator { /// # 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 /// diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 59e23c4d96056..563fb213d3763 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -7,6 +7,7 @@ // , 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: Sized { fn product>(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>(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>(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>(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>(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 index 0000000000000..6c07afb37b8a0 --- /dev/null +++ b/src/test/run-pass/iter-sum-overflow-debug.rs @@ -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 or the MIT license +// , 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::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::max_value()].iter().product::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [1, i32::max_value()].iter().cloned().sum::(); + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + [2, i32::max_value()].iter().cloned().product::(); + }); + 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 index 0000000000000..65ac1ef29ed6a --- /dev/null +++ b/src/test/run-pass/iter-sum-overflow-ndebug.rs @@ -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 or the MIT license +// , 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::(), + 1i32.wrapping_add(i32::max_value())); + assert_eq!([2i32, i32::max_value()].iter().product::(), + 2i32.wrapping_mul(i32::max_value())); + + assert_eq!([1i32, i32::max_value()].iter().cloned().sum::(), + 1i32.wrapping_add(i32::max_value())); + assert_eq!([2i32, i32::max_value()].iter().cloned().product::(), + 2i32.wrapping_mul(i32::max_value())); +} From 7bd25a304851afdf0ba1897a950220ed3ad0a215 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Mon, 12 Sep 2016 15:55:02 -0700 Subject: [PATCH 2/2] Remove stray attribute --- src/libcore/iter/traits.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 563fb213d3763..b55d6f96af9bf 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -587,7 +587,6 @@ 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>(iter: I) -> $a { iter.fold(0, Add::add) }