Inconsistent lifetime inference with return `impl Future`/`BoxFuture` and higher ranked lifetimes
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
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>
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked diesel_async example at src/run_query_dsl/mod.rs:783-817 and reproduce all three return-type variants using rustc 1.86.0-nightly. Compare the lifetime inference and diagnostics for the boxed future, impl Future, and async-block forms. Done means the inconsistent behavior is explained and the affected variants have consistent, correct lifetime handling or diagnostics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100