Skip to content

Inconsistent lifetime inference with return impl Future/BoxFuture and higher ranked lifetimes #135619

Open
@weiznich

Description

@weiznich

Compiling base line version: https://github.com/weiznich/diesel_async/blob/buggy_lifetimes/src/run_query_dsl/mod.rs#L783-L817

I encountered several inconsistent errors while working on the linked code:

Variant 1: (Remove the async move block and box the future directly)

impl<'b, Changes, Output, Tab, V> UpdateAndFetchResults<Changes, Output>
    for crate::AsyncPgConnection
where
    Output: Send + 'static,
    Changes:
        Copy + AsChangeset<Target = Tab> + Send + diesel::associations::Identifiable<Table = Tab>,
    Tab: diesel::Table + diesel::query_dsl::methods::FindDsl<Changes::Id> + 'b,
    diesel::dsl::Find<Tab, Changes::Id>: IntoUpdateTarget<Table = Tab, WhereClause = V>,
    diesel::query_builder::UpdateStatement<Tab, V, Changes::Changeset>:
        diesel::query_builder::AsQuery,
    diesel::dsl::Update<Changes, Changes>: methods::LoadQuery<'b, Self, Output>,
    V: Send + 'b,
    Changes::Changeset: Send + 'b,
    Tab::FromClause: Send,
{
    fn update_and_fetch<'life0, 'async_trait>(
        &'life0 mut self,
        changeset: Changes,
    ) -> BoxFuture<'async_trait, QueryResult<Output>>
    where
        Changes: 'async_trait,
        Changes::Changeset: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait,
    {
        diesel::update(changeset)
            .set(changeset)
            .get_result(self)
            .boxed()
    }
}

Results in the following compilation error:

error: lifetime may not live long enough
   --> src/run_query_dsl/mod.rs:809:9
    |
784 |   impl<'b, Changes, Output, Tab, V> UpdateAndFetchResults<Changes, Output>
    |        -- lifetime `'b` defined here
...
799 |       fn update_and_fetch<'life0, 'async_trait>(
    |                                   ------------ lifetime `'async_trait` defined here
...
809 | /         diesel::update(changeset)
810 | |             .set(changeset)
811 | |             .get_result(self)
812 | |             .boxed()
    | |____________________^ method was supposed to return data with lifetime `'async_trait` but it is returning data with lifetime `'b`
    |
    = help: consider adding the following bound: `'b: 'async_trait`

Variant 2: Use impl Future for the return type

impl<'b, Changes, Output, Tab, V> UpdateAndFetchResults<Changes, Output>
    for crate::AsyncPgConnection
where
    Output: Send + 'static,
    Changes:
        Copy + AsChangeset<Target = Tab> + Send + diesel::associations::Identifiable<Table = Tab>,
    Tab: diesel::Table + diesel::query_dsl::methods::FindDsl<Changes::Id> + 'b,
    diesel::dsl::Find<Tab, Changes::Id>: IntoUpdateTarget<Table = Tab, WhereClause = V>,
    diesel::query_builder::UpdateStatement<Tab, V, Changes::Changeset>:
        diesel::query_builder::AsQuery,
    diesel::dsl::Update<Changes, Changes>: methods::LoadQuery<'b, Self, Output>,
    V: Send + 'b,
    Changes::Changeset: Send + 'b,
    Tab::FromClause: Send,
{
    fn update_and_fetch<'life0, 'async_trait>(
        &'life0 mut self,
        changeset: Changes,
    ) -> impl Future<Output = QueryResult<Output>> + Send + 'async_trait
    where
        Changes: 'async_trait,
        Changes::Changeset: 'async_trait,
        'life0: 'async_trait,
        Self: 'async_trait,
    {
        async move {
            diesel::update(changeset)
                .set(changeset)
                .get_result(self)
                .await
        }
        .boxed()
    }
}

Error:

error[E0207]: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates
   --> src/run_query_dsl/mod.rs:784:6
    |
784 | impl<'b, Changes, Output, Tab, V> UpdateAndFetchResults<Changes, Output>
    |      ^^ unconstrained lifetime parameter

I would expect all three code variations to be the "same" in terms of involved lifetimes, but two of them do not compile with rather surprising errors.

Meta

rustc --version --verbose:

rustc 1.86.0-nightly (99db2737c 2025-01-16)
binary: rustc
commit-hash: 99db2737c91d1e4b36b2ffc17dcda5878bcae625
commit-date: 2025-01-16
host: x86_64-unknown-linux-gnu
release: 1.86.0-nightly
LLVM version: 19.1.7
Backtrace

<backtrace>

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-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