Lifetime error for containered return type


#1

Hey :slight_smile:

I’m having a fight with the lifetime checker.
Here’s the code:

// fight.rs
struct Obj<'a> {}

fn aggregate() -> Vec<Obj> {
    unimplemented!()
}

Not compiling with following error:

error[E0106]: missing lifetime specifier
 --> fight.rs:4:23
  |
4 | fn aggregate() -> Vec<Obj> {
  |                       ^^^ expected lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
  = help: consider giving it a 'static lifetime

error: aborting due to previous error(s)

I tried changing the return type with lifetime parameters:

fn aggregate<'a>() -> Vec<'a Obj>
fn aggregate<'a>() -> Vec<&'a Obj>
fn aggregate() -> Vec<'static Obj>
fn aggregate() -> Vec<&'static Obj>

And lots of other variations.
But nothing seems to work.

Can you help me please?


#2
  1. 'static is the only one that can work – you can’t produce any arbitrary lifetime yourself. aggregate() would have to take an object with a lifetime for it to be able to return another object (with the same lifetime).
  2. The lifetime is a type parameter of Obj and that’s how it should be specified where it’s used.

Here’s a compiling example.

// fight.rs
struct Obj<'a> {
    _phantom: ::std::marker::PhantomData<&'a ()>,
}

fn aggregate() -> Vec<Obj<'static>> {
    unimplemented!()
}

(Playground)

Note that to be able to define a struct with type parameters, you need to use all the type parameters. (These are needed for the compiler to figure out variances and to produce the correct drop code.)
I don’t know anything about your example, so I put a PhantomData implying that the struct semantically contains an immutably borrowed reference to something.

I’d need more details to understand what you precisely need here.


#5

Ah, thanks. My problem was I didn’t know where to put the lifetime in the return type. That solved my problem.

fn aggregate() -> Vec<Obj<'a>>

I need to use lifetimes because I store trait objects in a struct.

pub trait Provider {}

pub struct Plugin<'a> {
    name: String,
    providers: Vec<&'a (Provider + 'a)>,
}

:thumbsup: :heart: