Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the third rule of lifetime elision capture all cases for struct implementations?

Tags:

rust

lifetime

The third rule of lifetime elision says

If there are multiple input lifetime parameters, but one of them is &self or &mut self because this is a method, then the lifetime of self is assigned to all output lifetime parameters. This makes writing methods much nicer.

Here is the tutorial describing what happened for this function

fn announce_and_return_part(&self, announcement: &str) -> &str

There are two input lifetimes, so Rust applies the first lifetime elision rule and gives both &self and announcement their own lifetimes. Then, because one of the parameters is &self, the return type gets the lifetime of &self, and all lifetimes have been accounted for.

We can show that all the lifetimes are not accounted for since it is possible that announcement will have a different lifetime than &self:

struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("Attention please: {}", announcement);
        announcement
    }
}

fn main() {
    let i = ImportantExcerpt { part: "IAOJSDI" };
    let test_string_lifetime;

    {
        let a = String::from("xyz");
        test_string_lifetime = i.announce_and_return_part(a.as_str());
    }
    println!("{:?}", test_string_lifetime);   
}

The lifetime of announcement is not as long as &self, so it is not correct to associate the output lifetime to &self, shouldn't the output lifetime be associated to the longer of the input?

Why is the third rule of lifetime elision a valid way to assign output lifetime?

like image 758
Jal Avatar asked Sep 20 '17 23:09

Jal


People also ask

How does lifetime work in Rust?

Lifetimes are what the Rust compiler uses to keep track of how long references are valid for. Checking references is one of the borrow checker's main responsibilities. Lifetimes help the borrow checker ensure that you never have invalid references.

What are lifetime parameters rust?

Rust uses lifetime parameters to avoid such potential run-time errors. Since the compiler doesn't know in advance whether the if or the else block will execute, the code above won't compile and an error message will be printed that says, “a lifetime parameter is expected in compare 's signature.”

What is Anonymous lifetime rust?

'_ , the anonymous lifetime Rust 2018 allows you to explicitly mark where a lifetime is elided, for types where this elision might otherwise be unclear. To do this, you can use the special lifetime '_ much like you can explicitly mark that a type is inferred with the syntax let x: _ = ..; .


1 Answers

No, the elision rules do not capture every possible case for lifetimes. If they did, then there wouldn't be any elision rules, they would be the only rules and we wouldn't need any syntax to specify explicit lifetimes.

Quoting from the documentation you linked to, emphasis mine:

The patterns programmed into Rust's analysis of references are called the lifetime elision rules. These aren't rules for programmers to follow; the rules are a set of particular cases that the compiler will consider, and if your code fits these cases, you don't need to write the lifetimes explicitly.

The elision rules don't provide full inference: if Rust deterministically applies the rules but there's still ambiguity as to what lifetimes the references have, it won't guess what the lifetime of the remaining references should be. In this case, the compiler will give you an error that can be resolved by adding the lifetime annotations that correspond to your intentions for how the references relate to each other.


The lifetime of announcement is not as long as &self, so it is not correct to associate the output lifetime to &self

Why is the third rule of lifetime elision a valid way to assign output lifetime?

"correct" is probably not the right word to use here. What the elision rules have done is a valid way, it just doesn't happen to be what you might have wanted.

shouldn't the output lifetime be associated to the longer of the input?

Yes, that would be acceptable for this example, it's just not the most common case, so it's not what the elision rules were aimed to do.

See also:

  • Why are explicit lifetimes needed in Rust?
  • When do I need to specify explicit lifetimes in Rust?
  • When is it useful to define multiple lifetimes in a struct?
  • Why would you ever use the same lifetimes for references in a struct?
like image 72
Shepmaster Avatar answered Sep 30 '22 18:09

Shepmaster