Repository navigation
Open
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsAsyncAwait-PolishAsync-await issues that are part of the "polish" areaAsync-await issues that are part of the "polish" areaAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
Code:
use std::future::Future;
pub async fn bar() {
foo(|x| baz(x)).await;
}
pub async fn baz(x: &u8) -> bool {
if *x == 1 {
false
} else {
true
}
}
pub async fn foo<F, T>(f: F) -> bool
where
F: Fn(&u8) -> T,
T: Future<Output = bool>,
{
f(&32).await
}produces following error:
error: lifetime may not live long enough
--> src/lib.rs:4:13
|
4 | foo(|x| baz(x)).await;
| -- ^^^^^^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is impl std::future::Future
| has type `&'1 u8`
Is this error correct? If yes, why?
following also doesn't work:
pub async fn bar() {
foo(baz).await;
}error (still not clear):
error[E0271]: type mismatch resolving `for<'r> <for<'_> fn(&u8) -> impl std::future::Future {baz} as std::ops::FnOnce<(&'r u8,)>>::Output == _`
--> src/lib.rs:4:5
|
4 | foo(baz).await;
| ^^^ expected bound lifetime parameter, found concrete lifetime
...
15 | pub async fn foo<F, T>(f: F) -> bool
| --- required by a bound in this
16 | where
17 | F: Fn(&u8) -> T,
| - required by this bound in `foo`
meta:
$ rustc --version --verbose
rustc 1.45.0 (5c1f21c3b 2020-07-13)
binary: rustc
commit-hash: 5c1f21c3b82297671ad3ae1e8c942d2ca92e84f2
commit-date: 2020-07-13
host: x86_64-unknown-linux-gnu
release: 1.45.0
LLVM version: 10.0
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsAsyncAwait-PolishAsync-await issues that are part of the "polish" areaAsync-await issues that are part of the "polish" areaAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.Async-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Type
Projects
- StatusShow more project fieldsIn progress (current sprint)
Activity
SNCPlay42 commentedon Jul 19, 2020
This note
Is supposed to define the lifetime
'2referred to by the error message by showing it as a parameter of the return type, but'2doesn't appear in the type anywhere, possibly because of the opaqueimpl Futuretype.cc #74072
nikomatsakis commentedon Jul 21, 2020
This code is invalid. The closure is given a
&u8, which is only valid during the closure execution. Butbaz(x)capturesxand embeds it into a future that is returned -- this future, when awaited, will (or could) attempt to usex, even though the closure itself has returned, and hencexis no longer valid.The error message here is obviously not great. We have specialized errors for these kinds of cases in closures normally, I'm not sure why it didn't trigger in this case.
nikomatsakis commentedon Jul 21, 2020
There isn't a great workaround that uses stable syntax to make this compile, interestingly. We discussed it some on Zulip.
The error message for a comparable scenario without async isn't that great either, actually, I am somewhat surprised (playground):
nikomatsakis commentedon Jul 21, 2020
Returning a reference to a local variable is somewhat better (playground):
Rollup merge of rust-lang#74661 - SNCPlay42:lifetime-names-refactor, …
Rollup merge of rust-lang#74661 - SNCPlay42:lifetime-names-refactor, …
Rollup merge of rust-lang#76468 - SNCPlay42:lifetime-names, r=Mark-Si…
WinLinux1028 commentedon May 27, 2021
If the Future which returned by f(&32) awaited out of &32's lifetime, I think so too.
But if not, this code is valid.
This code will work:
eholk commentedon Sep 8, 2021
One of the things I find surprising here is when the error messages talk about
'1and'2. It's not really clear where these lifetimes would come from, although presumably they are some implied or inferred lifetime that's not written explicitly. Would it be possible to have rustc give some more information about where these come from, such as what values are borrowed with each lifetime?13 remaining items
vincenzopalazzo commentedon May 4, 2023
Okay, after spending some time on it, I've come up with a summary.
This is the complete example that includes the error, and also explains why this code will not work.
But it seems that, upon further reflection, the point made by @WinLinux1028 and analyzed by @eholk is correct. I wasn't able to find a counterexample where this code doesn't work. However, I do need to say that the solution proposed by @estebank is more attractive to me because it exactly describes what the callback does (since I don't like using 'static lifetimes).
Here is the revised code:
Furthermore, both synchronous and asynchronous code produce the same error. Therefore, I believe that this issue should be addressed for both types of code, rather than just the asynchronous function.
As a result, I intend to propose this matter for discussion at the upcoming async triage meeting, in order to receive feedback on the solution suggested by @eholk for inclusion in the compiler.
I did not check in deep, but this looks like another instance #102201
@rustbot label -AsyncAwait-Triaged +I-async-nominated
eholk commentedon Sep 25, 2023
We revisited this in @rust-lang/wg-async triage today. We think the behavior of the compiler is correct, but there's room to improve the error message. We'll spend some more time iterating on what an improved error message would look like.
traviscross commentedon Sep 25, 2023
Here's the minimal reproduction of this issue:
Playground link
(Thanks to @compiler-errors.)
timvermeulen commentedon Aug 17, 2024
This restricts
footo only callfwith references that are valid for any arbitrary lifetime'a, would that ever actually be useful? I expect this pattern to mostly arise when the function needs to call the closure with a reference to a local variable.Dylan-DPC commentedon Nov 14, 2025
Current error: