Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding explicit lifetimes causes compilation error #131336

Open
varqox opened this issue Oct 6, 2024 · 0 comments
Open

Adding explicit lifetimes causes compilation error #131336

varqox opened this issue Oct 6, 2024 · 0 comments
Labels
needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.

Comments

@varqox
Copy link

varqox commented Oct 6, 2024

Compiler version 1.81.0.

I am writing an asynchronous function that takes asynchronous callback, I managed to write it so that it compiles:

pub trait Callback<State> {
    type Output: Future<Output = ()>;

    fn call(&self, state: State) -> Self::Output;
}

impl<State, F, Fut> Callback<State> for F
where
    F: Fn(State) -> Fut,
    Fut: Future<Output = ()>,
{
    type Output = Fut;

    fn call(&self, state: State) -> Self::Output {
        self(state)
    }
}

pub async fn aaa<State, Cb>(state: &mut State, callback: &Cb)
where
    for<'state> Cb: Callback<&'state mut State>,
{
}

pub async fn bbb<State, Cb>(state: &mut State) {
    async fn callback<State>(state: &mut State) {}
    aaa(state, &callback).await;
}

However, if I try to add explicit lifetimes to the Callback trait, I get compilation error:

error[E0309]: the parameter type `State` may not live long enough
   --> src/storage.rs:252:33
    |
250 | impl<'state, State, F, Fut> Callback<'state, State> for F
    |      ------ the parameter type `State` must be valid for the lifetime `'state` as defined here...
251 | where
252 |     F: Fn(&'state mut State) -> Fut,
    |                                 ^^^ ...so that the reference type `&'state mut State` does not outlive the data it points at
    |
help: consider adding an explicit lifetime bound
    |
250 | impl<'state, State: 'state, F, Fut> Callback<'state, State> for F
    |                   ++++++++

for the following code:

pub trait Callback<'state, State> {
    type Output: Future<Output = ()>;

    fn call(&self, state: &'state mut State) -> Self::Output;
}

impl<'state, State, F, Fut> Callback<'state, State> for F
where
    F: Fn(&'state mut State) -> Fut,
    Fut: Future<Output = ()>,
{
    type Output = Fut;

    fn call(&self, state: &'state mut State) -> Self::Output {
        self(state)
    }
}

pub async fn aaa<State, Cb>(state: &mut State, callback: &Cb)
where
    for<'state> Cb: Callback<'state, State>,
{
}

pub async fn bbb<State, Cb>(state: &mut State) {
    async fn callback<State>(state: &mut State) {}
    aaa(state, &callback).await;
}

But if I fix it according to the suggestion, I get the following error:

error[E0310]: the parameter type `State` may not live long enough
   --> src/storage.rs:270:5
    |
270 |     aaa(state, &callback).await;
    |     ^^^^^^^^^^^^^^^^^^^^^
    |     |
    |     the parameter type `State` must be valid for the static lifetime...
    |     ...so that the type `State` will meet its required lifetime bounds
    |
help: consider adding an explicit lifetime bound
    |
268 | pub async fn bbb<State: 'static, Cb>(state: &mut State) {
    |                       +++++++++

error[E0310]: the parameter type `State` may not live long enough
   --> src/storage.rs:270:27
    |
270 |     aaa(state, &callback).await;
    |                           ^^^^^
    |                           |
    |                           the parameter type `State` must be valid for the static lifetime...
    |                           ...so that the type `State` will meet its required lifetime bounds
    |
help: consider adding an explicit lifetime bound
    |
268 | pub async fn bbb<State: 'static, Cb>(state: &mut State) {
    |                       +++++++++

for the code

pub trait Callback<'state, State> {
    type Output: Future<Output = ()>;

    fn call(&self, state: &'state mut State) -> Self::Output;
}

impl<'state, State: 'state, F, Fut> Callback<'state, State> for F
where
    F: Fn(&'state mut State) -> Fut,
    Fut: Future<Output = ()>,
{
    type Output = Fut;

    fn call(&self, state: &'state mut State) -> Self::Output {
        self(state)
    }
}

pub async fn aaa<State, Cb>(state: &mut State, callback: &Cb)
where
    for<'state> Cb: Callback<'state, State>,
{
}

pub async fn bbb<State, Cb>(state: &mut State) {
    async fn callback<State>(state: &mut State) {}
    aaa(state, &callback).await;
}

I thing something is not correct about treating explicit lifetimes by the compiler, or I added the lifetimes incorrectly.
Please help.

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Oct 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.
Projects
None yet
Development

No branches or pull requests

2 participants