I'm trying to implement the following trait, where the <'baz> is required for a later impl<'baz> Baz<'baz> for T where T: OtherTrait†.
trait Baz<'baz>: Clone {
fn baz(&'baz mut self);
fn bazzed(&self) -> Self {
let mut x = self.clone();
x.baz();
x
}
}
Rustc understandably fails:
Compiling playground v0.0.1 (/playground)
error[E0309]: the parameter type `Self` may not live long enough
--> src/lib.rs:6:9
|
6 | x.baz();
| ^
|
= help: consider adding an explicit lifetime bound `Self: 'baz`...
= note: ...so that the type `Self` is not borrowed for too long
error[E0309]: the parameter type `Self` may not live long enough
--> src/lib.rs:6:11
|
6 | x.baz();
| ^^^
|
= help: consider adding an explicit lifetime bound `Self: 'baz`...
= note: ...so that the reference type `&'baz mut Self` does not outlive the data it points at
For more information about this error, try `rustc --explain E0309`.
error: could not compile `playground` due to 2 previous errors
So I follow its suggestion:
trait Baz<'baz>: Clone {
fn baz(&'baz mut self);
fn bazzed(&self) -> Self
where
Self: 'baz
{
let mut x = self.clone();
x.baz();
x
}
}
And I don't quite understand what it's not liking now...
Compiling playground v0.0.1 (/playground)
error[E0597]: `x` does not live long enough
--> src/lib.rs:9:9
|
1 | trait Baz<'baz>: Clone {
| ---- lifetime `'baz` defined here
...
9 | x.baz();
| ^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `x` is borrowed for `'baz`
10 | x
11 | }
| - `x` dropped here while still borrowed
error[E0505]: cannot move out of `x` because it is borrowed
--> src/lib.rs:10:9
|
1 | trait Baz<'baz>: Clone {
| ---- lifetime `'baz` defined here
...
9 | x.baz();
| -------
| |
| borrow of `x` occurs here
| argument requires that `x` is borrowed for `'baz`
10 | x
| ^ move out of `x` occurs here
Some errors have detailed explanations: E0505, E0597.
For more information about an error, try `rustc --explain E0505`.
error: could not compile `playground` due to 2 previous errors
I tried making Self: 'static too but that did not help either. What am I missing here?
† The <'baz> I need for another trait, that looks roughly like:
trait ReturnIteratorMut<'item> {
type IterType: Iterator<Item = &'item mut Thing>;
fn iterator<'slf: 'item>(&'slf mut self) -> Self::IterType;
}
I want to implement Baz for all of these by applying baz() to every item in the iterator, so I need 'baz: 'item. This works fine with just the baz() method, it's only the bazzed() that it starts to complain at.
Let's first try to understand what's wrong with this code, without the compiler's help.
x.baz() requires x to live for 'baz. Since 'baz can be any lifetime this means x has to live for 'static. It does not - it is a local variable, and this is an error (you might want HRTB, but you said you want to focus on the compiler errors so I don't deal with the solution).
The compiler's second errors are just that - x does not live long enough, or, if we look at the opposite angle, x is borrowed for 'static and so we cannot move it (the compiler shows both errors in order to maximize displayed errors - sometimes it works, sometimes, like in this case, it leads to confusing errors being shown).
The first error(s) is a negligible result of this constraint, but it hides the actual error (for what it's worth, on nightly they're all shown together): x needs to live for 'static, but not just it does not, sometimes it is impossible for any variable of its type to be. Suppose Self is &'some_short_lifetime i32 - it cannot live for 'static, since it contains a shorter lifetime. This is the reason "Self may not live long enough`.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With