I've been reading a blog post (Giving, lending, and async closures) that presented a lending iterator trait that can also be used as a "regular" iterator:
trait LendingIterator {
type Item<'this>
where
Self: 'this;
fn next(&mut self) -> Option<Self::Item<'_>>;
}
fn take_two_v3<U, T>(t: &mut T) -> Option<(U, U)>
where
T: for<'a> LendingIterator<Item<'a> = U>,
{
let Some(i) = t.next() else { return None };
let Some(j) = t.next() else { return None };
Some((i, j))
}
I got curious and tried a different approach that didn't work:
fn take_two_v4<T>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)>
where
T: for<'a> LendingIterator<Item<'a>: 'static>, // <-- added `: 'static`
{
let Some(i) = t.next() else { return None };
let Some(j) = t.next() else { return None }; // <-- cannot borrow `*t` as mutable more than once at a time
Some((i, j))
}
My hope was that : 'static
would tell the compiler that Item
doesn't hold references to t
, but I'm clearly mistaken here.
Could someone please help me understand T: for<'a> LendingIterator<Item<'a>: 'static>
: is it a meaningful construct and what it actually means?