Let's assign some numbers to those elided and anonymous lifetimes (not real Rust syntax):
impl HighScores<'1> {
// ^^
pub fn new(scores: &'2 [u32]) -> Self { ... }
// ^^
}
Self
is HighScores<'1>
, so what this says is that new
can take a slice of any lifetime '2
and return a HighScores
of any lifetime '1
. What you want to say is that you can take a slice of some lifetime and return a HighScores
of the same lifetime:
impl<'a> HighScores<'a> {
pub fn new(scores: &'a [u32]) -> Self { ... }
}
Since new
returns Self
, its argument has to be a reference of the same lifetime as Self
. To do that we have to declare a named lifetime parameter and use it both in the impl
and in the signature of new
.
Lifetime elision doesn't mean lifetime inference: the compiler isn't looking at how you're using the lifetimes and filling them in with what makes sense. It's a pretty simple set of rules that only takes into account the current signature. An elided lifetime ('2
) never unifies with a lifetime parameter from an outer scope ('1
).