Skip to main content

core/iter/traits/
accum.rs

1use crate::iter;
2use crate::num::{Saturating, Wrapping};
3
4/// Trait to represent types that can be created by summing up an iterator.
5///
6/// This trait is used to implement [`Iterator::sum()`]. Types which implement
7/// this trait can be generated by using the [`sum()`] method on an iterator.
8/// Like [`FromIterator`], this trait should rarely be called directly.
9///
10/// [`sum()`]: Iterator::sum
11/// [`FromIterator`]: iter::FromIterator
12#[stable(feature = "iter_arith_traits", since = "1.12.0")]
13#[diagnostic::on_unimplemented(
14    message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
15    label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
16)]
17pub trait Sum<A = Self>: Sized {
18    /// Takes an iterator and generates `Self` from the elements by "summing up"
19    /// the items.
20    #[stable(feature = "iter_arith_traits", since = "1.12.0")]
21    fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
22}
23
24/// Trait to represent types that can be created by multiplying elements of an
25/// iterator.
26///
27/// This trait is used to implement [`Iterator::product()`]. Types which implement
28/// this trait can be generated by using the [`product()`] method on an iterator.
29/// Like [`FromIterator`], this trait should rarely be called directly.
30///
31/// [`product()`]: Iterator::product
32/// [`FromIterator`]: iter::FromIterator
33#[stable(feature = "iter_arith_traits", since = "1.12.0")]
34#[diagnostic::on_unimplemented(
35    message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
36    label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
37)]
38pub trait Product<A = Self>: Sized {
39    /// Takes an iterator and generates `Self` from the elements by multiplying
40    /// the items.
41    #[stable(feature = "iter_arith_traits", since = "1.12.0")]
42    fn product<I: Iterator<Item = A>>(iter: I) -> Self;
43}
44
45macro_rules! integer_sum_product {
46    (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
47        #[$attr]
48        impl Sum for $a {
49            #[ferrocene::prevalidated]
50            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
51                iter.fold(
52                    $zero,
53                    #[rustc_inherit_overflow_checks]
54                    |a, b| a + b,
55                )
56            }
57        }
58
59        #[$attr]
60        impl Product for $a {
61            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
62                iter.fold(
63                    $one,
64                    #[rustc_inherit_overflow_checks]
65                    |a, b| a * b,
66                )
67            }
68        }
69
70        #[$attr]
71        impl<'a> Sum<&'a $a> for $a {
72            #[ferrocene::prevalidated]
73            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
74                iter.fold(
75                    $zero,
76                    #[rustc_inherit_overflow_checks]
77                    |a, b| a + b,
78                )
79            }
80        }
81
82        #[$attr]
83        impl<'a> Product<&'a $a> for $a {
84            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
85                iter.fold(
86                    $one,
87                    #[rustc_inherit_overflow_checks]
88                    |a, b| a * b,
89                )
90            }
91        }
92    )*);
93    ($($a:ty)*) => (
94        integer_sum_product!(@impls 0, 1,
95                #[stable(feature = "iter_arith_traits", since = "1.12.0")],
96                $($a)*);
97        integer_sum_product!(@impls Wrapping(0), Wrapping(1),
98                #[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
99                $(Wrapping<$a>)*);
100    );
101}
102
103macro_rules! saturating_integer_sum_product {
104    (@impls $zero:expr, $one:expr, $doc:expr, #[$attr:meta], $($a:ty)*) => ($(
105        #[$attr]
106        #[doc = $doc]
107        impl Sum for $a {
108            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
109                iter.fold(
110                    $zero,
111                    |a, b| a + b,
112                )
113            }
114        }
115
116        #[$attr]
117        #[doc = $doc]
118        impl Product for $a {
119            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
120                iter.fold(
121                    $one,
122                    |a, b| a * b,
123                )
124            }
125        }
126
127        #[$attr]
128        #[doc = $doc]
129        impl<'a> Sum<&'a $a> for $a {
130            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
131                iter.fold(
132                    $zero,
133                    |a, b| a + b,
134                )
135            }
136        }
137
138        #[$attr]
139        #[doc = $doc]
140        impl<'a> Product<&'a $a> for $a {
141            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
142                iter.fold(
143                    $one,
144                    |a, b| a * b,
145                )
146            }
147        }
148    )*);
149    ($($a:ty)*) => (
150        saturating_integer_sum_product!(@impls Saturating(0), Saturating(1),
151                "The short-circuiting behavior of this implementation is unspecified. If you care about \
152                short-circuiting, use [`Iterator::fold`] directly.",
153                #[stable(feature = "saturating_iter_arith", since = "1.91.0")],
154                $(Saturating<$a>)*);
155    );
156}
157
158macro_rules! float_sum_product {
159    ($($a:ident)*) => ($(
160        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
161        impl Sum for $a {
162            #[ferrocene::prevalidated]
163            fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
164                iter.fold(
165                    -0.0,
166                    #[rustc_inherit_overflow_checks]
167                    |a, b| a + b,
168                )
169            }
170        }
171
172        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
173        impl Product for $a {
174            fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
175                iter.fold(
176                    1.0,
177                    #[rustc_inherit_overflow_checks]
178                    |a, b| a * b,
179                )
180            }
181        }
182
183        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
184        impl<'a> Sum<&'a $a> for $a {
185            #[ferrocene::prevalidated]
186            fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
187                iter.fold(
188                    -0.0,
189                    #[rustc_inherit_overflow_checks]
190                    |a, b| a + b,
191                )
192            }
193        }
194
195        #[stable(feature = "iter_arith_traits", since = "1.12.0")]
196        impl<'a> Product<&'a $a> for $a {
197            fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
198                iter.fold(
199                    1.0,
200                    #[rustc_inherit_overflow_checks]
201                    |a, b| a * b,
202                )
203            }
204        }
205    )*)
206}
207
208integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
209saturating_integer_sum_product! { u8 u16 u32 u64 u128 usize }
210float_sum_product! { f16 f32 f64 f128 }
211
212#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
213impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
214where
215    T: Sum<U>,
216{
217    /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
218    /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
219    /// occur, the sum of all elements is returned.
220    ///
221    /// # Examples
222    ///
223    /// This sums up every integer in a vector, rejecting the sum if a negative
224    /// element is encountered:
225    ///
226    /// ```
227    /// let f = |&x: &i32| if x < 0 { Err("Negative element found") } else { Ok(x) };
228    /// let v = vec![1, 2];
229    /// let res: Result<i32, _> = v.iter().map(f).sum();
230    /// assert_eq!(res, Ok(3));
231    /// let v = vec![1, -2];
232    /// let res: Result<i32, _> = v.iter().map(f).sum();
233    /// assert_eq!(res, Err("Negative element found"));
234    /// ```
235    fn sum<I>(iter: I) -> Result<T, E>
236    where
237        I: Iterator<Item = Result<U, E>>,
238    {
239        iter::try_process(iter, |i| i.sum())
240    }
241}
242
243#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
244impl<T, U, E> Product<Result<U, E>> for Result<T, E>
245where
246    T: Product<U>,
247{
248    /// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
249    /// elements are taken, and the [`Err`] is returned. Should no [`Err`]
250    /// occur, the product of all elements is returned.
251    ///
252    /// # Examples
253    ///
254    /// This multiplies each number in a vector of strings,
255    /// if a string could not be parsed the operation returns `Err`:
256    ///
257    /// ```
258    /// let nums = vec!["5", "10", "1", "2"];
259    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
260    /// assert_eq!(total, Ok(100));
261    /// let nums = vec!["5", "10", "one", "2"];
262    /// let total: Result<usize, _> = nums.iter().map(|w| w.parse::<usize>()).product();
263    /// assert!(total.is_err());
264    /// ```
265    fn product<I>(iter: I) -> Result<T, E>
266    where
267        I: Iterator<Item = Result<U, E>>,
268    {
269        iter::try_process(iter, |i| i.product())
270    }
271}
272
273#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
274impl<T, U> Sum<Option<U>> for Option<T>
275where
276    T: Sum<U>,
277{
278    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
279    /// elements are taken, and the [`None`] is returned. Should no [`None`]
280    /// occur, the sum of all elements is returned.
281    ///
282    /// # Examples
283    ///
284    /// This sums up the position of the character 'a' in a vector of strings,
285    /// if a word did not have the character 'a' the operation returns `None`:
286    ///
287    /// ```
288    /// let words = vec!["have", "a", "great", "day"];
289    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
290    /// assert_eq!(total, Some(5));
291    /// let words = vec!["have", "a", "good", "day"];
292    /// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
293    /// assert_eq!(total, None);
294    /// ```
295    fn sum<I>(iter: I) -> Option<T>
296    where
297        I: Iterator<Item = Option<U>>,
298    {
299        iter::try_process(iter, |i| i.sum())
300    }
301}
302
303#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
304impl<T, U> Product<Option<U>> for Option<T>
305where
306    T: Product<U>,
307{
308    /// Takes each element in the [`Iterator`]: if it is a [`None`], no further
309    /// elements are taken, and the [`None`] is returned. Should no [`None`]
310    /// occur, the product of all elements is returned.
311    ///
312    /// # Examples
313    ///
314    /// This multiplies each number in a vector of strings,
315    /// if a string could not be parsed the operation returns `None`:
316    ///
317    /// ```
318    /// let nums = vec!["5", "10", "1", "2"];
319    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
320    /// assert_eq!(total, Some(100));
321    /// let nums = vec!["5", "10", "one", "2"];
322    /// let total: Option<usize> = nums.iter().map(|w| w.parse::<usize>().ok()).product();
323    /// assert_eq!(total, None);
324    /// ```
325    fn product<I>(iter: I) -> Option<T>
326    where
327        I: Iterator<Item = Option<U>>,
328    {
329        iter::try_process(iter, |i| i.product())
330    }
331}