Why do I need to provide lifetimes for a struct

2019-08-20 19:58发布

问题:

I'm trying to get my head around the way that generics and lifetimes interact. Consider:

use std::ops::Add;

struct Gloop<'a, T: Add> {
    wumpus: &'a Wumpus<T>,
}

trait Wumpus<T: Add> {
    fn fleeb(&self, x: &T) -> bool;
}

struct Mimsy {
    jubjub: f64,
}

impl<T: Add> Wumpus<T> for Mimsy {
    fn fleeb(&self, x: &T) -> bool {
        return (x + x) > 0;
    }
}

fn main() {
    let a = Mimsy { jubjub: 1. };
    let b = Gloop::<i32> { wumpus: &a };
    println!("{}", b.fleeb(1));
}

Which yields:

error[E0309]: the parameter type `T` may not live long enough
 --> src/main.rs:4:5
  |
3 | struct Gloop<'a, T: Add> {
  |                  -- help: consider adding an explicit lifetime bound `T: 'a`...
4 |     wumpus: &'a Wumpus<T>,
  |     ^^^^^^^^^^^^^^^^^^^^^
  |
note: ...so that the reference type `&'a Wumpus<T> + 'a` does not outlive the data it points at
 --> src/main.rs:4:5
  |
4 |     wumpus: &'a Wumpus<T>,
  |     ^^^^^^^^^^^^^^^^^^^^^

Which object in my program is the one which may not live long enough? Nowhere in either Gloop or Mimsy (or any Wumpus<T>) is a T ever stored.

回答1:

Note: I answered this, but think the question is actually a duplicate of

"The parameter type `C` may not live long enough", when it doesn't need to

This answer can be deleted if others agree.


Nowhere in either Gloop or Mimsy (or any Wumpus<T>) is a T ever stored.

Rust doesn't care about what you do, but what you could do. There are no signature differences between these two structs:

struct Alpha<T> {
    a: T,
}

struct Beta<T> {
    b: fn(&T),
}

Namely, you can't tell the difference between the two and Beta could become Alpha without noticeable external changes to a consumer. Once you have a generic type, you need to handle any possibility.

You can either add T: 'static or add a lifetime and add T: 'a.

See also:

  • Why the lifetime is needed at all
    • Why is the bound `T: 'a` required in order to store a reference `&'a T`?
    • Parameter type may not live long enough?
  • For similar reasons, Rust only checks function signatures
    • Why are explicit lifetimes needed in Rust?
  • Once you are past that, you need to adjust your trait bounds
    • How to write a trait bound for adding two references of a generic type?