43

I read here that

A shared reference type is written &type, or &'a type when you need to specify an explicit lifetime.

Understood & is for shared reference but did not understand what is the difference between type and 'a in Rust language

In another location I read this code:

#[derive(Debug)]
struct Person<'a> {
    name: &'a str,
    age: u8
}

fn main() {
    let name = "Peter";
    let age = 27;
    let peter = Person { name, age };

    // Pretty print
    println!("{:#?}", peter);
}

What does 'a in the struct Person<'a> { } means? and can I build the same struct using struct Person<'type> { } or struct Person<T> { }?

And what is the meaning of name: &'a str?

And how can I re-code it, if want to avoid using the <'a>

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203

1 Answers1

86

I found this and this and this and this that explains my question.

The 'a reads ‘the lifetime a’. Technically, every reference has some lifetime associated with it, but the compiler lets you elide (i.e. omit, see "Lifetime Elision") them in common cases.

fn bar<'a>(...)

A function can have ‘generic parameters’ between the <>s, of which lifetimes are one kind. The <> is used to declare lifetimes. This says that bar has one lifetime, 'a.

Rust has two main types of strings: &str and String. The &str are called ‘string slices’. A string slice has a fixed size, and cannot be mutated. It is a reference to a sequence of UTF-8 bytes.

let greeting = "Hello there."; // greeting: &'static str

"Hello there." is a string literal and its type is &'static str. A string literal is a string slice that is statically allocated, meaning that it’s saved inside our compiled program, and exists for the entire duration it runs. The greeting binding is a reference to this statically allocated string. Any function expecting a string slice will also accept a string literal.

In the above example

struct Person<'a> {  }

requires to contain <'a> as the name is defined using:

name: &'a str,

which is called by:

let name = "Peter";

If interested to avoid the usage of 'a then the above code can be re-written as:

#[derive(Debug)]
struct Person {    // instead of: struct Person<'a> {
    name: String,  // instead of: name: &'a str 
    age: u8
}

fn main() {
    let name = String::from("Peter");  // instead of: let name = "Peter"; which is &'static str
    let age = 27;
    let peter = Person { name, age };

    // Pretty print
    println!("{:#?}", peter);
}

As mentioned by @DimitrisSfounis in the comments, in short, "Why is 'a there?" ---- Because the struct definition ties it to a referenced object (in this case, every struct Person instance is referencing a &str) you want to specificly declare an arbitary lifetime and tie these two things together: You want a struct Person instance to only live as long as its referenced object (hence Person<'a> and name: &'a str) so dangling references after each other's death is avoided.

Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
  • 6
    Thank you for the detailed concise explanation. – jking Jul 21 '20 at 01:34
  • 9
    Hi, I found your answer not simple enough for Rust newbies like me. After looking around for quite some time, I'd like to offer a simpler explanation to the question: "Why is `'a` there?" ---- Because the struct definition ties it to a referenced object (in this case, every `struct Person` instance is referencing a `&str`) you want to specificly declare an arbitary lifetime and tie these two things together: You want a `struct Person` instance to **only live as long** as its referenced object (hence `Person<'a>` and `name: &'a str`) so dangling references after each other's death is avoided. – Dimitris Sfounis Jan 22 '21 at 15:36
  • 2
    Thanks @DimitrisSfounis I added your statement to the answer, hope it is helping other :) – Hasan A Yousef Jan 23 '21 at 13:55
  • 1
    @DimitrisSfounis thank you for the newbie lvl answer haha. This newbie certainly appreciates it <3 – Dorian Crutcher Jul 01 '21 at 21:20