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