Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

rust - Explicit lifetime declarations in trait objects held by structs

In the answer to this question there's a discussion of how to refer to trait objects held by structs which requires the following syntax:

struct Bar<'a> {
    foo: &'a (Foo + 'a),
}

This is per RFC 438

Could I ask for more explanation of the double lifetime declaration? Levans said:

You have to specify the lifetime two times : once for the lifetime of the reference, and once for the trait object itself, because traits can be implemented for references, and if the underlying object is a reference, you must specify its lifetime as well.

I understand the notion of a lifetime for the reference in the struct. But I don't understand why the lifetime isn't for the object that the trait is a trait on. Put another way, I don't know what it means to hold a reference for a trait without holding a reference to the underlying thing that it's a trait for.

Is there a case where the trait and the underlying object would have different lifetimes? What would it mean to hold onto a reference to a trait without holding on to the underlying thing the trait is on?

Asking yet another way, why can't Rust just do The Right Thing(tm) with:

struct Bar<'a> {
    foo: &'a Foo,
}

where The Right Thing(tm) would be to interpret that as equivalent to the declaration above?

Sorry to bombard with questions, but I felt like I was doing something pretty basic (use a trait as a generic facet), and I had to go down the rabbit hole pretty deep, and I'd like to understand why the rabbit hole is that deep.

The error message: error: explicit lifetime bound required was decidedly unhelpful, because there is a lifetime bound already.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

why the lifetime isn't for the object that the trait is a trait on

Because the reference to the trait object and the trait object itself might have different lifetimes. Here's an example of a trait that is implemented for a reference:

trait Quack {
    fn quack(&self) { println!("Quack") }
}

impl<'a> Quack for &'a bool {}

struct MasterQuack<'a> {
    q: &'a (Quack + 'a),
}

fn main() {
    let a = true;
    // a.quack(); // Nope, not defined
    (&a).quack();

    // MasterQuack {q: &a}; // Nope, this would be a reference to a boolean, which isn't Quack
    MasterQuack {q: &&a};
}

One thing to note is that it's perfectly fine to have &'a (Trait + 'b) - that is, a reference to a trait that itself has a / is a reference, and those lifetimes are different. You said as much with

Is there a case where the trait and the underlying object would have different lifetimes?

But it's more a case of "the underlying object has references with different lifetimes".

why can't Rust just do The Right Thing(tm)

As of RFC 599 this now compiles:

struct Bar<'a> {
    foo: &'a Foo,
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.7k users

...