Async trait that takes a sync closure, "does not live long enough"

Hi, I am trying to write trait that takes a closure as argument to modify a value and get it back.
I am on nightly and using generic_associated_types and type_alias_impl_trait features.

Here is the code in question

pub trait EditRegister<R, A, E>
where
    for<'a> R: EditableRegister<Address = A, Error = E> + 'a,
{
    /// The return type of the write
    type Output<'a>: Future<Output = Result<(), E>>
    where
        Self: 'a;

    /// Edit a register. The closure takes a reference to the register,
    /// the same register must be edited, then returned.
    fn edit<'a, 'w, F>(&'a mut self, f: F) -> Self::Output<'a>
    where
        F: FnOnce(&'w mut R) -> &'w R + 'a;
}

/// Implementation of the edit register
impl<I, R, A, E> EditRegister<R, A, E> for I
where
    for<'a> R: EditableRegister<Address = A, Error = E> + 'a, 
    I: RegisterInterface<R, A, E>, // Provide the read and write register functions
    for<'a> A: 'a,
    for<'a> E: 'a,
{
    type Output<'a> = impl Future<Output = Result<(), E>> +'a where Self: 'a;

    fn edit<'a: 'w, 'w, F>(&'a mut self, f: F) -> Self::Output<'a>
    where
        F: FnOnce(&'w mut R) -> &'w R + 'a,
    {
        async {
            let mut val = self.read_register().await?;
            let res = f(&mut val);
            self.write_register(res).await
        }
    }
}

Here is the output of the compilation

❯ cargo build
   Compiling device-register-async v0.1.0 

error[E0597]: `val` does not live long enough
   --> device-register-async/src/lib.rs:123:25
    |
117 |     fn edit<'a: 'w, 'w, F>(&'a mut self, f: F) -> Self::Output<'a>
    |                 -- lifetime `'w` defined here
...
123 |             let res = f(&mut val);
    |                       --^^^^^^^^-
    |                       | |
    |                       | borrowed value does not live long enough
    |                       argument requires that `val` is borrowed for `'w`
124 |             self.write_register(res).await
125 |         }
    |         - `val` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.
error: could not compile `device-register-async` due to previous error

How come val is dropped while still borrowed? Shouldn't the closure only borrow it for the lifetime 'w, which should be shorter than 'a? Now I guess is that since it's a future, the closure can be evaluated later, but the lifetime 'a is already given to it. Is there any workaround to make sure that val is not dropped? Or maybe I need to pin the closure?

Any help is appreciated

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.