Writing a generic function that takes an iterable container as parameter in Rust

This is a case for Higher Ranked Trait Bounds (HRTB).

The point is that you do not want &L to implement IntoIterator<Item = &T> for one lifetime but for all potential lifetimes that L may happen to have.

In this case, you need to use a Higher Ranked Trait Bound: for<'a> will take care of introducing the lifetime name whilst simultaneously signaling to the compiler that the clause using it should be valid for all possible values of 'a.

This means:

impl<T, L> Observer<L> for SumObserver<T>
where
    for<'a> &'a L: IntoIterator<Item = &'a T>,
{
    fn update(&self, observable: &Observable<L>) {
        let mut sum: i64 = 0;
        for item in observable.get() {
            sum += (self.get_value)(item);
        }
        *self.current_sum.borrow_mut() = sum;
    }
}

which compiles (at least in isolation).

See also:

Leave a Comment