0

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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
trbabb
  • 1,894
  • 18
  • 35
  • I believe this question to already be answered by the answers in [Parameter type may not live long enough?](https://stackoverflow.com/q/29740488/155423); [The parameter type `T` may not live long enough when writing a binary searching tree](https://stackoverflow.com/q/45194762/155423); [The parameter type `T` may not live long enough](https://stackoverflow.com/q/49918896/155423); [Parameter type may not live long enough](https://stackoverflow.com/q/32625583/155423), etc. – Shepmaster Apr 23 '18 at 01:41
  • Please take the time to perform some basic research effort before posting your question and then *show* that research effort in the question. People who answer questions on Stack Overflow do so with the intent that people in the future will read those answers in the future. Ignoring their hard work makes Stack Overflow mostly meaningless and less useful of a resource. – Shepmaster Apr 23 '18 at 01:42
  • In your examples, a specific object of type T is either being stored or returned by the generic object. It seems clear that the required lifetime is that of the object being transferred/stored. In my example, we are not storing or returning any T, so whose lifetime are we talking about? I am not able to see the correspondence to your examples, but of course I am new to Rust. – trbabb Apr 23 '18 at 02:06
  • 1
    Just because the error message is the same doesn't mean the source of the problem is the same. Please make an effort to understand the question in good faith, just as you expect effort from the asker. People who ask questions on StackOverflow are hoping to get intelligent help that they could not get from a search engine, and knee-jerk dismissiveness makes it an unfriendly and less useful resource for the learners that need it most. – trbabb Apr 23 '18 at 02:07
  • I apologize that I've offended you. A vast majority of people asking questions don't take the time to do any research, and it's noticeable. That's why Stack Overflow has rules about how to ask questions, and that's why I'm encouraging you to **show** that effort that you made before asking the question *in the question itself*. Otherwise SO becomes a wasteland of "here's my (half-provided) code, make it work" followed up by people saying "Yeah, I did research. No, nothing anyone has ever asked is remotely like what I'm asking, trust me". – Shepmaster Apr 23 '18 at 02:49
  • 1
    For example, if you had started by putting the content of [your comment](https://stackoverflow.com/questions/49972233/why-do-i-need-to-provide-lifetimes-for-a-structs-generic-parameters-which-are-n/49972692#comment86960965_49972233) into the question along with some links to these existing questions that you had looked at, we wouldn't never have had this discussion. You can *still* [edit] your question to make it the question it should have been and all these comments will disappear. – Shepmaster Apr 23 '18 at 03:03
  • And piling on, I leave these comments because *I want every question and question asker to be excellent*. It'd be easier to leave downvotes and move on, but I don't believe that will actually make anything better. I only do that for "lost causes". – Shepmaster Apr 23 '18 at 03:06
  • 2
    What about [“The parameter type `C` may not live long enough”, when it doesn't need to](https://stackoverflow.com/q/49299043/155423)? That seems like more of an exact duplicate... when you were doing your research, what caused you to reject that as answering your question? – Shepmaster Apr 23 '18 at 03:09
  • Possible duplicate of ["The parameter type \`C\` may not live long enough", when it doesn't need to](https://stackoverflow.com/questions/49299043/the-parameter-type-c-may-not-live-long-enough-when-it-doesnt-need-to), The solution is as simple as the compiler say `struct Gloop<'a, T: 'a + Add>` – Stargateur Apr 23 '18 at 03:17

1 Answers1

2

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:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366