Skip to content

Random lifetime may not live long enough from other part of the code #96645

Open
@DzenanJupic

Description

@DzenanJupic

I just stumbled across a weird and inconsistent behaviour, that seems unreasonable to me.

The project I'm working on is a big company project (closed source) with quite some files. While fixing a bug and editing one line in one module (src/dispatcher/compiler/module_range.rs) the compiler suddenly decided to reject the code of a function from a completely different module (src/services/module_state_service.rs) that has absolutely nothing to do with the module I'm working on.

The change that I made:

fn get_next_module_start(&self, module: &FunctionalModule<'a>, starter: &'a Fmid) -> Result<usize> {
        // -- snip --
        WorkflowIterator::exe_path_iter(
            self.modules,
            starter,
            |m| m.fmd.next_module.as_ref().into_option(),
-           |m| super::sort_exe_paths(&m.fmd.exe_paths),
+           |m| (m != module).then(|| super::sort_exe_paths(&m.fmd.exe_paths)).into_iter().flatten(),
            |m| m.md.kind,
        )
        // -- snip --
}

The compiler error:

error: lifetime may not live long enough
  --> src/services/module_state_service.rs:35:44
   |
32 |           &'_ self,
   |            -- let's call the lifetime of this reference `'1`
33 |           workflow_id: &WorkflowGroupId,
34 |           fmid: &Fmid,
   |                 - let's call the lifetime of this reference `'2`
35 |       ) -> Option<RwLockReadGuard<'_, [u8]>> {
   |  ____________________________________________^
36 | |         let map_guard = self.module_state.read().await;
37 | |
38 | |         let contains_state = map_guard
...  |
49 | |         }))
50 | |     }
   | |_____^ associated function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`

error: lifetime may not live long enough
  --> src/services/module_state_service.rs:47:9
   |
32 |           &'_ self,
   |            -- let's call the lifetime of this reference `'1`
33 |           workflow_id: &WorkflowGroupId,
34 |           fmid: &Fmid,
   |                 - let's call the lifetime of this reference `'2`
...
47 | /         Some(RwLockReadGuard::map(map_guard, |map| {
48 | |             &**map.get(workflow_id).unwrap().get(fmid).unwrap()
49 | |         }))
   | |___________^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

The function the compiler complains about:

pub async fn get_module_state(
    &'_ self,
    workflow_id: &WorkflowGroupId,
    fmid: &Fmid,
) -> Option<RwLockReadGuard<'_, [u8]>> {
    let map_guard = self.module_state.read().await;

    let contains_state = map_guard
        .get(workflow_id)
        .map(|map| map.contains_key(fmid))
        .unwrap_or_default();

    if !contains_state {
        return None;
    }

    Some(RwLockReadGuard::map(map_guard, |map| {
        &**map.get(workflow_id).unwrap().get(fmid).unwrap()
    }))
}

When undoing the one-line change, the code compiled fine again, and after redoing it, it failed to compile again.
Now, after indenting a few pieces of code, to make pasting them into GitHub easier, the compiler again accepts the code.
I'm also no longer able to recreate the error.

I know, that's essentially nothing to work with, and I'm not even able to recreate the issue myself anymore, but it seems worth reporting to me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-NLLArea: Non-lexical lifetimes (NLL)A-incr-compArea: Incremental compilationNLL-completeWorking towards the "valid code works" goalP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions