I'm trying to reproduce an error I'm having on my small app in Rust.
I'm trying to use async closure as lambda functions (very tipical in other languages).
But I just found out that this is a bit difficult in Rust:
REPL: https://www.rustexplorer.com/b/bcwggm.
Error:
error: lifetime may not live long enough
--> src/main.rs:55:9
|
54 | let result = player_change_name(&|musts| {
| ------ return type of closure is Pin<Box<(dyn Future<Output = Result<Player, ()>> + Send + '2)>>
| |
| has type `PlayerMusts<'1>`
55 | / Box::pin(async {
56 | | let o = Player {
57 | | id: musts.actual.id.clone(),
58 | | name: "Frank".to_string(),
... |
62 | | Ok(o)
63 | | })
| |__________^ returning this value requires that `'1` must outlive `'2`
Code:
/*
[dependencies]
tokio = { version = "1.26.0", features = ["macros", "rt-multi-thread"] }
*/
use std::{future::Future, pin::Pin};
#[derive(Debug, Default, Clone)]
pub struct Player {
pub id: String,
pub name: String,
pub team: Option<String>,
}
struct PlayerMusts<'a> {
pub actual: &'a Player,
pub other: &'a str,
}
async fn player_change_name<'a>(
lambda: &(dyn 'a
+ Fn(PlayerMusts) -> Pin<Box<dyn Future<Output = Result<Player, ()>> + Send + 'a>>
+ Sync),
) -> Result<Player, ()> {
// I need to await for many things in here
// Eg. for DB connection pool...
// let mut db_connection = pool.begin().await?;
// Here I can query the actual player, I'm faking it now...
let actual = Player {
id: "1".to_string(),
name: "Bob".to_string(),
team: None,
};
let worked_player = lambda(PlayerMusts {
actual: &actual,
other: "Other",
})
.await?;
// I'm saving the lambda result here, I'm faking it now...
// let result = db_connection.save(&worked_player, &actual).await?;
let result = worked_player;
// db_connection.save_and_close().await?;
Ok(result)
}
#[tokio::main]
async fn main() -> Result<(), ()> {
let result = player_change_name(&|musts| {
Box::pin(async {
let o = Player {
id: musts.actual.id.clone(),
name: "Frank".to_string(),
team: None,
};
Ok(o)
})
})
.await?;
dbg!(result);
Ok(())
}