1

How can I return a reference wrapped in a struct and what lifetime annotation is required? I am having a tough time formulating my exact question, but the following example illustrates what I am trying to do. I have a struct C that contains a reference to a struct B that requires lifetime parameters. I want a function on C that returns the reference to B wrapped in another struct Borrower that functions as an interface.

When compiling this I get an error when returning Borrower: 'cannot infer an appropriate lifetime for lifetime parameter 'b due to conflicting requirements'. How can I resolve this issue? What lifetime parameters can I enter? I feel like both 'a and 'b are not the right lifetimes.

Playground

struct C<'a, 'b> {
    ref2: &'a mut B<'b>,
}

impl<'a, 'b> C<'a, 'b> {
    fn get_borrower(&mut self) -> Borrower {
        Borrower { ref3: self.ref2 }
    }
}

struct Borrower<'a, 'b> {
    ref3: &'a mut B<'b>,
}

impl<'a, 'b> Borrower<'a, 'b> {
    fn print_and_add(&mut self) {
        println!("ref is {}", self.ref3.ref1.i);
        self.ref3.ref1.i += 1;
    }
}

struct B<'a> {
    ref1: &'a mut A,
}

struct A {
    i: u32,
}

fn main() {
    let mut a = A { i: 10 };
    let mut b = B { ref1: &mut a };
    let mut c = C { ref2: &mut b };

    for _ in 0..10 {
        let mut borrower = c.get_borrower();
        borrower.print_and_add();
    }
}
Francis Gagné
  • 60,274
  • 7
  • 180
  • 155
Aart Stuurman
  • 3,188
  • 4
  • 26
  • 44

1 Answers1

3

The issue is specifically in this method:

impl<'a, 'b> C<'a, 'b> {
    fn get_borrower(&mut self) -> Borrower {
        Borrower { ref3: self.ref2 }
    }
}

We need to help the compiler understand which lifetime parameters are expected in the returned Borrower, because the inferred lifetimes here will be incorrect: The lifetime elision Borrower can be expanded to Borrower<'_, '_> where the anonymous lifetimes are both the lifetime of &mut self; If we call it 's, the equivalent signature would be:

    fn get_borrower<'s>(&'s mut self) -> Borrower<'s, 's> {

This is clearly not right, because we know that the second lifetime is expected to be 'b, as directly described by field ref2 of type B<'b>. With the following signature (and after fixing unrelated errors), the code compiles successfully:

    fn get_borrower(&mut self) -> Borrower<'_, 'b> {

The fun part is in the first parameter. One could be inclined to assume that we want it to be 'a instead of 's, but that would still lead to conflicting lifetimes:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
 --> src/main.rs:7:9
  |
7 |         Borrower { ref3: self.ref2 }
  |         ^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime `'s` as defined on the method body at 6:21...
 --> src/main.rs:6:21
  |
6 |     fn get_borrower<'s>(&'s mut self) -> Borrower<'a, 'b> {
  |                     ^^
note: ...so that reference does not outlive borrowed content
 --> src/main.rs:7:26
  |
7 |         Borrower { ref3: self.ref2 }
  |                          ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
 --> src/main.rs:5:6
  |
5 | impl<'a, 'b> C<'a, 'b> {
  |      ^^
note: ...so that the expression is assignable
 --> src/main.rs:7:9
  |
7 |         Borrower { ref3: self.ref2 }
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: expected `Borrower<'a, 'b>`
             found `Borrower<'_, '_>`

This is because we are retrieving ref2 behind a mutable reference to self, and that one has its own lifetime. We cannot just move it out of self by force to fulfill the lifetime 'a, nor can we pass a &'s mut &'a mut B<'b> instead. Therefore, returning a Borrower<'s, 'b> is the right thing to do: as it is implicit that 'a: 's ('a outlives 's), the covariance in this lifetime will enable this method to narrow the mutable reference &'a mut B<'b> into its subtype &'s mut B<'b>.

 ---------- 
| 'a       |
| ------   |
|| 's   | ---> Borrower<'s, 'b>
||      |  |
| ------   |
 ----------

See also:

E_net4
  • 27,810
  • 13
  • 101
  • 139