在类型声明中使用 `for<'a>` 抛出“引用生命周期不出现在特征输入类型中”

问题描述 投票:0回答:0

我刚刚在类型声明中使用

for<'a>
发现了一个怪癖:https://www.rustexplorer.com/b/vwnvu9

error[E0582]: binding for associated type `Output` references lifetime `'b`, which does not appear in the trait input types
  --> src/main.rs:14:29
   |
14 |     dyn for<'b> Fn(ArgT) -> Pin<Box<dyn Future<Output = Result<ResT, ()>> + Send + 'b>> + Sync;
   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0582`.

这真的很奇怪......至少可以这么说。

代码:

/*
[dependencies]
async-trait = { version = "0.1.68" }
tokio = { version = "1.26.0", features = ["macros", "rt-multi-thread"] }
*/

use std::{future::Future, marker::PhantomData, pin::Pin, sync::Arc};

trait Trait: Send + Sync + PlayerTrait {}

impl<T: PlayerTrait> Trait for T {}

pub type Lambda<ArgT, ResT> =
    dyn for<'b> Fn(ArgT) -> Pin<Box<dyn Future<Output = Result<ResT, ()>> + Send + 'b>> + Sync;

#[async_trait::async_trait]
trait PlayerTrait: Send + Sync {
    async fn player_change_name<'a>(
        &self,
        input: &PlayerChangeNameInput,
        // lambda: &(dyn for<'b> Fn(
        //     PlayerMusts<'b, 'a>,
        // ) -> Pin<Box<dyn Future<Output = Result<Player, ()>> + Send + 'b>>
        //       + Sync),
        lambda: &Lambda<PlayerMusts, Player>,
    ) -> Result<Player, ()>;
}

struct PlayerChangeNameInput {
    pub name: String,
}

struct Player {
    pub id: String,
    pub name: String,
}

struct PlayerMusts<'a, 'b: 'a> {
    _lifetime: PhantomData<&'b ()>,
    pub actual: &'a Player,
    // pub other: &'a str,
}

#[async_trait::async_trait]
impl PlayerTrait for Repo {
    async fn player_change_name<'a>(
        &self,
        input: &PlayerChangeNameInput,
        lambda: &(dyn for<'b> Fn(
            PlayerMusts<'b, 'a>,
        ) -> Pin<Box<dyn Future<Output = Result<Player, ()>> + Send + 'b>>
              + Sync),
    ) -> Result<Player, ()> {
        // I need input here
        dbg!(&input.name);

        // 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(),
        };

        let worked_player = lambda(PlayerMusts {
            _lifetime: PhantomData,
            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)
    }
}

struct HandlerImpl {
    repo: Arc<Repo>,
}

fn new_handler(repo: Arc<Repo>) -> Box<dyn Handler> {
    Box::new(HandlerImpl { repo })
}

#[async_trait::async_trait]
trait Handler: Send + Sync {
    async fn handle(&self, input: &PlayerChangeNameInput, whoami: &str) -> Result<Player, ()>;
}

#[async_trait::async_trait]
impl Handler for HandlerImpl {
    async fn handle(&self, input: &PlayerChangeNameInput, whoami: &str) -> Result<Player, ()> {
        // use whoami here...
        dbg!(whoami);

        let result = self
            .repo
            .player_change_name(input, &|musts| {
                Box::pin(async {
                    let o = Player {
                        id: musts.actual.id.clone(),
                        name: input.name.to_string(),
                    };

                    Ok(o)
                })
            })
            .await?;

        Ok(result)
    }
}

pub struct Repo {
    // pub pool: Arc<DbPool>,
}

impl Repo {
    pub fn new() -> Self {
        Self {}
    }
}

#[tokio::main]
async fn main() -> Result<(), ()> {
    let db_repo = Arc::new(Repo::new());

    let handler = new_handler(db_repo);

    let whoami = "Myself";

    let fake_input = &PlayerChangeNameInput {
        name: "Frank".to_string(),
    };

    let result = handler.handle(fake_input, whoami).await?;

    dbg!(result.name);

    Ok(())
}
rust closures
© www.soinside.com 2019 - 2024. All rights reserved.