Why are lifetime specifiers not required [sometimes] in Rust for generics?

Viewed 108

I was looking at the Microsoft Rust guide and while reading the generics chapters, I came across the following problem.

Consider the two following pieces of code:

struct Point<T>
{
    x: T,
    y: T,
}
fn main()
{
    let intro = Point{ x: "Hello", y: "World" };    
}
struct Point
{
    x: &str,
    y: &str,
}
fn main()
{
    let intro = Point{ x: "Hello", y: "World" };    
}

Both have x and y have the types &str. Why is the compiler able to infer lifetime in first piece and not in the second?

1 Answers

In the first case:

struct Point<T>
{
    x: T,
    y: T,
}
fn main()
{
    let intro = Point{ x: "Hello", y: "World" };    
}

The type definition is valid for whatever T, and especially for whatever lifetime the reference have if there are references. It's a generics, it's meant to adapt (and to lead to several different "real" structs if necessary).

The concrete struct you use is for T being &'static str but it could be another lifetime.

In the second case

struct Point
{
    x: &str,
    y: &str,
}
fn main()
{
    let intro = Point{ x: "Hello", y: "World" };    
}

There's no generic. So it must be a completely defined type. Meaning there has to be a lifetime if there are references. You don't specify the lifetime, so it's an error.

If you want to have only the lifetime free to decide, then it's a generic again:

struct Point<'a> {
    x: &'a str,
    y: &'a str,
}
fn main()
{
    let intro = Point{ x: "Hello", y: "World" };    
}

Alternatively, if you want your Point to be only valid for static references, you can define it as

struct Point {
    x: &'static str,
    y: &'static str,
}
Related