Writing a generic function that takes an iterable container as parameter in Rust
<p>I want to write a generic function that takes any immutably borrowed iterable container such as an array, <code>Vec</code>, <code>BTreeSet</code>, etc. Since this function is part of a trait that I am implementing, I am not able to change the signature of it, so it's not possible to directly take an iterator as parameter and I also can't introduce any lifetime parameters to the function signature.</p>

<h2>Context</h2>

<p>I tried to implement the observer pattern in Rust. The observable and the observer look as follows:</p>

<pre><code>struct Observable&lt;T&gt; {
    value: T,
}

impl&lt;T&gt; Observable&lt;T&gt; {
    pub fn get(&amp;self) -&gt; &amp;T {
        &amp;self.value
    }
}

trait Observer&lt;T&gt; {
    fn update(&amp;self, &amp;Observable&lt;T&gt;);
}
</code></pre>

<p>(Some functions that were irrelevant to my problem are omitted)</p>

<p>It is now my objective to write an observer that can be used with arbitrary iterable containers which hold items that can be assigned a value. It is supposed to keep track of the sum of values of the items in the container and therefore holds the current sum and a function that calculates the value of any item. It should implement the <code>Observer</code> trait so the sum can be updated each time the container changes.</p>

<pre><code>use std::cell::RefCell;

struct SumObserver&lt;T&gt; {
    current_sum: RefCell&lt;i64&gt;,
    get_value: Fn(&amp;T) -&gt; i64,
}
</code></pre>

<h2>Approaches so far</h2>

<p>I have unsuccessfully tried to get the <code>update</code> function to compile for quite some time. The following is one of the versions of the function that I tried:</p>

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

<p>However, the compiler complains that both parameter types <code>T</code> and <code>L</code> might not live long enough:</p>

<pre class="lang-none prettyprint-override"><code>error[E0309]: the parameter type `T` may not live long enough
  --&gt; src/lib.rs:22:1
   |
22 |   impl&lt;'a, T, L&gt; Observer&lt;L&gt; for SumObserver&lt;T&gt;
   |   ^        - help: consider adding an explicit lifetime bound `T: 'a`...
   |  _|
   | |
23 | | where
24 | |     &amp;'a L: IntoIterator&lt;Item = &amp;'a T&gt;,
25 | | {
...  |
32 | |     }
33 | | }
   | |_^
   |
note: ...so that the reference type `&amp;'a T` does not outlive the data it points at
  --&gt; src/lib.rs:22:1
   |
22 | / impl&lt;'a, T, L&gt; Observer&lt;L&gt; for SumObserver&lt;T&gt;
23 | | where
24 | |     &amp;'a L: IntoIterator&lt;Item = &amp;'a T&gt;,
25 | | {
...  |
32 | |     }
33 | | }
   | |_^
</code></pre>

<p>The error message even stays the same if the whole function body is commented out. If I also remove the <code>where</code>-clause, the compilation works.</p>

<p>If I follow the compiler's suggestion to add explicit lifetime bounds to the parameter types:</p>

<pre><code>impl&lt;'a, T: 'a, L: 'a&gt; Observer&lt;L&gt; for SumObserver&lt;T&gt;
</code></pre>

<p>The compiler gives the following error:</p>

<pre class="lang-none prettyprint-override"><code>error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --&gt; src/lib.rs:28:32
   |
28 |         for item in observable.get() {
   |                                ^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 26:5...
  --&gt; src/lib.rs:26:5
   |
26 | /     fn update(&amp;self, observable: &amp;Observable&lt;L&gt;) {
27 | |         let mut sum: i64 = 0;
28 | |         for item in observable.get() {
29 | |             sum += (self.get_value)(item);
30 | |         }
31 | |         *self.current_sum.borrow_mut() = sum;
32 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --&gt; src/lib.rs:28:21
   |
28 |         for item in observable.get() {
   |                     ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 22:6...
  --&gt; src/lib.rs:22:6
   |
22 | impl&lt;'a, T: 'a, L: 'a&gt; Observer&lt;L&gt; for SumObserver&lt;T&gt;
   |      ^^
   = note: ...so that the types are compatible:
           expected std::iter::IntoIterator
              found std::iter::IntoIterator
</code></pre>

<p>I don't understand the problem with lifetimes in this function. At any point where this function is called, the compiler should make sure that the borrow of <code>observable</code> lasts at least until the function returns. At that time, any borrow of <code>observable</code> has gone out of scope.</p>