Returning iterators and lifetime annotation woes

As an addition, this nesting rule is particular to mutable references.

If we have:

r: &'a mut GiveReferenceMut<'b, X>
// GiveReferenceMut is something that's a bit like a mutable reference.
// For example a mutable reference iterator..

the innermost things must live the longest. Formally this is X: 'b (because we have mutable references to X), and then the outer layer requires X: 'a (“X outlives 'a”) and 'b: 'a (“'b outlives 'a”)

For mutable references, the rule is that if we access GiveReferenceMut through &'a mut, we can only get a borrow of scope at most 'a, which is always the smaller (or equal) of the scopes 'a and 'b.

The reasoning is simple: Mutable references are a unique access token. We have unique access to the “GiveReferenceMut” only through the scope 'a, so that's the only scope our derived borrows can in turn be guaranteed unique.


Shared references are much simpler:

r: &'a GiveReference<'b, X>
// GiveReference is something that's a bit like a shared reference.
// For example a shared reference iterator..

We still have the rule that the innermost things must live the longest. X: 'b, and X: 'a, and 'b: 'a.

Shared references are implicitly copyable. Even if 'a is much shorter than 'b, we know that for the whole scope of 'b, there are shared references alive that point to values of X. It is of no harm to give out more of these. So through r we can get &'b X references without problem.

1 Like