Reference from reference. cannot infer an appropriate lifetime


#1

How do I can set a reference from reference in a struct? I tried to solve this case using raw-pointer, but it requires an unsafe section for any usage of the field

An example:

struct Connection;

struct Pool {
    connection: Connection,
}

impl Pool {
    fn new () -> Pool {
        Pool {
            connection: Connection{},
        }    
    }
    
    fn connection(&self) -> &Connection {
        &self.connection
    }
}

struct Foo<'a> {
    connection: &'a Connection,
}

impl<'a> Foo<'a> {
    fn new(pool: &Pool) -> Foo<'a> {
        Foo {
            connection: pool.connection()
        }
    }
}

fn main() {
    let pool = Pool::new();
    let foo1 = Foo::new(&pool);
}

expanded example in playground


#2

Since pool.connection returns a reference that has same lifetime as pool, we need to constrain the lifetimes here a bit, as shown below:

impl<'a> Foo<'a>
{
    fn new<'b:'a>(pool: &'b Pool) -> Foo<'a>
    {
        Foo {
            connection: pool.connection()
        }
    }
}

This says that 'b outlives 'a, which translates to the pool outliving the Foo instance, and that’s what we want because Foo has a reference to a Connection whose lifetime is that of the pool.


#3

Wow, it’s helpful, thanks! =)
One more little question - how i can move method new to separate trait?


#4

What exactly do you mean? Right now you have no traits in the example above, so it’s a bit unclear what you’re asking :slight_smile:


#5

You right, i mean something like this

impl<'a> Constructor for Foo<'a>
{
    fn new<'b:'a>(pool: &'b Pool) -> Foo<'a>
    {
        Foo {
            connection: pool.connection()
        }
    }
}

// some mistake here
pub trait Constructor
{
    fn new<'b>(&'b Container) -> Self;
}

#6

Something like this maybe:

trait FromPool<'p, T> {
    fn new(pool: &'p T) -> Self;
}

impl<'a, 'p: 'a> FromPool<'p, Pool> for Foo<'a> {
    fn new(pool: &'p Pool) -> Self {
        Foo { connection: pool.connection() }
    }
}

#7

Yep, I move lifetimes from method to declaration of implementation, and that work. Thank you!