Repository: rust
Issue: Inconsistent lifetime inference with return `impl Future`/`BoxFuture` and higher ranked lifetimes
Labels: A-impl-trait,C-bug,needs-triage

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

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)

```rust
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

```rust
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
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

`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
```

<!--
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
-->
<details><summary>Backtrace</summary>
<p>

```
<backtrace>
```

</p>
</details>