The third rule is that, if there are multiple input lifetime parameters, but one of them is &self or &mut self because this is a method, the lifetime of self is assigned to all output lifetime parameters.
Looks like below code is in compliance with 3rd rule, but it doesn't compile, maybe I am misunderstanding rule 3.
I understand that if annote 2nd parameter with lifetime 'a it will be ok.
The rule is being applied properly, but you're misunderstanding the error:
error: lifetime may not live long enough
--> src/lib.rs:7:1
|
6 | pub fn longest(&self, str1: & str) -> &str {
| - - let's call the lifetime of this reference `'1`
| |
| let's call the lifetime of this reference `'2`
7 | str1
| ^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
The second parameter has a different lifetime from the self parameter, and it isn't guaranteed to live longer; therefore the lifetime '1 can't be downcast into the lifetime '2.
The true desugaring of longest looks more like this:
error: lifetime may not live long enough
--> src/lib.rs:7:9
|
6 | pub fn longest<'s, 'o>(self: &'s Test<'a>, str1: &'o str) -> &'s str {
| -- -- lifetime `'o` defined here
| |
| lifetime `'s` defined here
7 | str1
| ^^^^ method was supposed to return data with lifetime `'s` but it is returning data with lifetime `'o`
|
= help: consider adding the following bound: `'o: 's`
The code doesn't work (with elision or when desugared) because there's no relation between 'o and 's; 'o might be shorter than 's and thus the &'o str cannot coerce to an &'s str.
There is an implicit 'a: 's bound due to the presence of &'s Test<'a> as an input type. The compiler understands that an &'s Test<'a> where 's is shorter than 'a is not well-formed and can never exists, and exploits this knowledge.
You can see that this implicit bound is present in the OP by doing something like this:
impl<'a> Test<'a> {
pub fn longest(&self, str1: & str) -> &str {
let s: &'a str = "";
s
}
pub fn longest_more_explicit<'s>(&'s self, str1: & str) -> &'s str {
let s: &'a str = "";
let s: &'s str = s;
s
}
}
Yes, yes, I have misunderstood the rule, the rule is saying that outputs have same lifetime with the &self, but it never says other parameter is guaranteed to live longer than &self (the output's lifetime).
Thank you bro and thank you @Yokin