Reputation: 21666
If I remove the 'static
lifetime of the final argument, the program compiles. If I add it back, it fails. To me, it seems both should be valid. Minimal reproduction:
use std::io;
struct Foo {
user: String,
pass: String,
}
impl Foo {
async fn not_works(
&mut self,
user: &str,
pass: &str,
app_name: &'static str,
) -> io::Result<()> {
self.user = user.to_string() + app_name;
self.pass = pass.to_string();
self.do_stuff().await
}
async fn works(&mut self, user: &str, pass: &str, app_name: &str) -> io::Result<()> {
self.user = user.to_string() + app_name;
self.pass = pass.to_string();
self.do_stuff().await
}
async fn do_stuff(&self) -> io::Result<()> {
Ok(())
}
}
#[tokio::main]
async fn main() {
let mut foo = Foo {
user: "".to_string(),
pass: "".to_string(),
};
foo.not_works("test", "password", "foobar").await.unwrap();
}
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> src/main.rs:14:10
|
14 | ) -> io::Result<()> {
| ^^^^^^^^^^^^^^
|
note: hidden type `impl Future` captures lifetime smaller than the function body
--> src/main.rs:14:10
|
14 | ) -> io::Result<()> {
| ^^^^^^^^^^^^^^
It's much more likely the bug is in my understanding and not the compiler though. What am I missing?
Upvotes: 5
Views: 5666
Reputation: 100110
This is a limitation of the async fn
implementation. Basically, it tries to unify all lifetimes to be the same, and in this case they can't be all 'static
.
This works:
fn workaround<'a>(
&'a mut self,
user: &'a str,
pass: &'a str,
app_name: &'static str,
) -> impl Future<Output = io::Result<()>> + 'a {
async move {
self.user = user.to_string() + app_name;
self.pass = pass.to_string();
self.do_stuff().await
}
}
Upvotes: 7