Lifetime problem - Cannot infer an appropriate lifetime

Hello all,

First off, I apologise if this isn't the right place for this kind of question.

I'm new to Rust. I believe I grasp the "why" of lifetimes, but I don't really understand the "how". Whenever the compiler tells me I need to put 'a somewhere, I do it not really knowing the effect it has.

I am getting the following error:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:25:17
   |
25 |         let v = MemoryValueSource {
   |                 ^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 24:5...
  --> src/main.rs:24:5
   |
24 | /     pub(crate) fn process(&mut self) {
25 | |         let v = MemoryValueSource {
26 | |             memory: self.memory,
27 | |         };
28 | |         
29 | |         // Do some processing on 'v' by passing it to appropriate funcs.
30 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:26:21
   |
26 |             memory: self.memory,
   |                     ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'_` as defined on the impl at 17:16...
  --> src/main.rs:17:16
   |
17 | impl Processor<'_> {
   |                ^^
note: ...so that the expression is assignable
  --> src/main.rs:26:21
   |
26 |             memory: self.memory,
   |                     ^^^^^^^^^^^
   = note: expected `&mut MemoryController<'_>`
              found `&mut MemoryController<'_>`

I have a Processor which holds a reference to a MemoryController, which in turn holds a reference to SomeKindOfData.
In the Processors process() func, I want to create a MemoryValueSource that borrows memory from self.

If I remove SomeKindOfData completely, everything works. Please, I need someone to explain what mistake I have done with my lifetime annotations.

pub struct SomeKindOfData {
    some_data: i32,
}

pub struct MemoryController<'a> {
    data: &'a SomeKindOfData,
}

pub struct Processor<'a> {
    memory: &'a mut MemoryController<'a>,
}

pub struct MemoryValueSource<'a> {
    memory: &'a mut MemoryController<'a>,
}

impl Processor<'_> {
    pub(crate) fn new<'a>(mem: &'a mut MemoryController<'a>) -> Processor<'a> {
        Processor {
            memory: mem,
        }
    }
    
    pub(crate) fn process(&mut self) {
        let v = MemoryValueSource {
            memory: self.memory,
        };
        
        // Do some processing on 'v' by passing it to appropriate funcs.
    }
}

impl MemoryController<'_> {
    pub fn new<'a>(data: &'a SomeKindOfData) -> MemoryController<'a> {
        MemoryController {
            data,
        }
    }
}

fn main() {
    let data = SomeKindOfData { some_data: 0 };
    let mut memory = MemoryController::new(&data);
    
    let mut processor = Processor::new(&mut memory);
    
    processor.process();
}

(Playground)

In this case, there are two different lifetimes that you care about: the lifetime of SomeKindOfData and the lifetime of the MemoryController. By giving them the same name (’a), you’ve told the compiler that they are valid in identical regions of the program.

I don’t understand the mechanics of this well enough to explain why this is a problem, but the net effect is similar to a deadlock, as &mut references are effectively single-threaded mutexes. Your code works properly after separating these two lifetimes by giving each of them their own name:

pub struct SomeKindOfData {
    some_data: i32,
}

pub struct MemoryController<'data> {
    data: &'data SomeKindOfData,
}

pub struct Processor<'ctl, 'data:'ctl> {
    memory: &'ctl mut MemoryController<'data>,
}

pub struct MemoryValueSource<'ctl, 'data:'ctl> {
    memory: &'ctl mut MemoryController<'data>,
}

(Playground)


Altenatively, and perhaps more idiomatically, you can have most your structs own their fields instead of just holding references:

pub struct SomeKindOfData {
    some_data: i32,
}

pub struct MemoryController {
    data: SomeKindOfData,
}

pub struct Processor {
    memory: MemoryController,
}

pub struct MemoryValueSource<'mem> {
    memory: &'mem mut MemoryController,
}

(Playground)

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.