Cannot infer an appropriate lifetime with mut reference field


#1

While trying to create an iterator I’ve stumbled upon error[E0495]. I’ve simplified the code to the following. S1::x represents a buffer which I’d like to change from within get() and return a reference to it.

 struct S1 {
    x: u32,
}

struct S2<'a> {
    s1: &'a S1,
}

impl<'a> S2<'a> {
    fn get(&mut self) -> &'a u32 {
        &self.s1.x
    }
}

struct S3<'a> {
    s1: &'a mut S1, // this "mut" is the only difference from S2
}

impl<'a> S3<'a> {
    fn get(&mut self) -> &'a u32 {
        //error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
        &self.s1.x
    }
}

fn main() {}

(Playground)

Errors:

   Compiling playground v0.0.1 (file:///playground)
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src/main.rs:21:9
   |
21 |         &self.s1.x
   |         ^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 20:5...
  --> src/main.rs:20:5
   |
20 | /     fn get(&mut self) -> &'a u32 {
21 | |         &self.s1.x
22 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:21:9
   |
21 |         &self.s1.x
   |         ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 19:1...
  --> src/main.rs:19:1
   |
19 | impl<'a> S3<'a> {
   | ^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:21:9
   |
21 |         &self.s1.x
   |         ^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.


#2

You’ll want S3::get() to have a signature like this:

fn get(&mut self) -> &u32

Mutable borrows, like the s1 inside S3, can only move or be reborrowed for a shorter lifetime; immutable borrows don’t have that restriction, which allows S2 to work as you wanted.