1

I was going through some solutions to exercise exercises and couldn't figure out why an explicit lifetime declaration is required?

#[derive(Debug)]
pub struct HighScores<'a> {
    scores: &'a [u32],
}

impl<'a> HighScores<'a> {
    pub fn new(scores: &'a [u32]) -> Self {
        HighScores { scores }
    }

    pub fn scores(&self) -> &[u32] {
        self.scores
    }

    pub fn latest(&self) -> Option<u32> {
        self.scores.last().cloned()
    }

    pub fn personal_best(&self) -> Option<u32> {
        self.scores.iter().max().cloned()
    }

    pub fn personal_top_three(&self) -> Vec<u32> {
        let mut res_vec = self.scores.to_vec();

        res_vec.sort_unstable_by(|a, b| a.cmp(b).reverse());
        res_vec.truncate(3);

        res_vec
    }
}

Source Exercism Exercise

Aditya Arora
  • 303
  • 2
  • 12
  • 1
    Because the slice is just borrowed and not owned (like a `Vec` would be). – hellow Jan 23 '20 at 11:59
  • @Stargateur, it does but I couldn't relate that much for this snippet of code. – Aditya Arora Jan 23 '20 at 12:12
  • ask about learn a language is too broad read https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html. or ask a more focus question https://stackoverflow.com/a/31625653/7076153 answer you – Stargateur Jan 23 '20 at 12:16
  • @hellow, Just to be clear, since it is a reference which may outlive the struct, we should declare the lifetime explicitly? – Aditya Arora Jan 24 '20 at 09:28

1 Answers1

2

This is due to the lifetime elision rules

Consider following not working new fn:

pub fn new(scores: &[u32]) -> Self {
    HighScores { scores }
}
error[E0621]: explicit lifetime required in the type of `scores`

Same as:

pub fn new(scores: &[u32]) -> HighScores<'a> {
    HighScores { scores }
}

Returning Self is the same as returning the type you're currently implementing (HighScores<'a>), now you have one elided lifetime for input &[u32] that differs from the explicit lifetime in your return type, which is illegal for your example struct.

It should also be noted that the lifetimes declared in your impl Header are not available for lifetime elision for an input of a function.

You can either solve this by setting the lifetime for your input:

pub fn new(scores: &'a [u32]) -> Self {
    HighScores { scores }
}

Or elide the output lifetime:

pub fn new(scores: &[u32]) -> HighScores<'_> {
    HighScores { scores }
}
Mad Matts
  • 1,118
  • 10
  • 14
  • Thanks for the answer. Initially, I wasn't explicitly declaring the lifetime for the reference in my struct, but that was silly not doing that as the reference may outlive the struct or vice versa. Correct me if I am wrong. – Aditya Arora Jan 24 '20 at 09:27