I got stuck while trying to implementing an Iter
and IterMut
for my container using only safe rust (the std
use unsafe rust). After extracting the important parts, I got this code below.
struct Iter<'a>(&'a i32);
impl<'a> Iter<'a> {
fn get<'b>(self: &'b Iter<'a>) -> &'a i32 {
self.0
}
}
and:
struct IterMut<'a>(&'a mut i32);
impl<'a> IterMut<'a> {
fn get<'b>(self: &'b IterMut<'a>) -> &'a i32 {
self.0
}
}
and the error:
error: lifetime may not live long enough
--> src/lib.rs:13:9
|
11 | impl<'a> IterMut<'a> {
| -- lifetime `'a` defined here
12 | fn get<'b>(self: &'b IterMut<'a>) -> &'a i32 {
| -- lifetime `'b` defined here
13 | self.0
| ^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
|
= help: consider adding the following bound: `'b: 'a`
My question is how does the compiler know the impl of Iter
work but not the IterMut
? Does it have anything to do with variance?
I understand why it should work for Iter
and not for IterMut
, but not why. It should work because the get
method return a reference of lifetime 'a
which might not coincide with lifetime 'b
of the iter object. For Iter
this is fine, we just have two immutable reference to i32
(the iter and the return of get
). But for IterMut
we would have a mutable reference (the iter) and an immutable reference (the return of get) to i32
, which is a no no.
For the error part, the compiler suggests making the return reference borrow the iter (ie. make its lifetime lives at most the lifetime of the iter). That is why it suggests 'b: 'a
.