如何在 actix_web FromRequest 特征实现中 return 映射未来?

How to return a mapped future in an actix_web FromRequest trait implementation?

我有以下 actix_web FromRequest 特性的实现:

impl ::actix_web::FromRequest for Box<dyn SessionRepository> {
    type Error = ::actix_web::Error;
    type Future =
        ::futures::future::MapOk<::futures::future::Ready<Result<Self, Self::Error>>, ???>;
    type Config = ();

    fn from_request(
        req: &::actix_web::HttpRequest,
        payload: &mut actix_web::dev::Payload,
    ) -> Self::Future {
        RealSessionRepository::from_request(&req, payload).map_ok(|dep| Box::new(dep))
    }
}

由于 return 类型是 FnOnce,我不知道如何实际设置 return 类型。根据错误消息,它应该是 FnOnce<(std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)>,)>,但这告诉我 fnOnce 无效,因为它在编译时不是已知大小。

RealSessionRepository::from_request return 是未来,也是 FromRequest 特征的实现。

像这样插入 FnOnce 定义:

impl ::actix_web::FromRequest for Box<dyn SessionRepository> {
    type Error = ::actix_web::Error;
    type Future = ::futures::future::MapOk<
        ::futures::future::Ready<Result<Self, Self::Error>>,
        FnOnce(RealSessionRepository) -> Box<(dyn SessionRepository + 'static)>,
    >;
    type Config = ();

    fn from_request(
        req: &::actix_web::HttpRequest,
        payload: &mut actix_web::dev::Payload,
    ) -> Self::Future {
        RealSessionRepository::from_request(&req, payload).map_ok(|dep| Box::new(dep))
    }
}

给出以下一组错误消息:

error[E0277]: the size for values of type `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)` cannot be known at compilation time
  --> api-server\src\db\sessions.rs:32:6
   |
32 | impl ::actix_web::FromRequest for Box<dyn SessionRepository> {
   |      ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required because of the requirements on the impl of `core::future::future::Future` for `futures_util::future::try_future::map_ok::MapOk<futures_util::future::ready::Ready<std::result::Result<std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)>, actix_web::Error>>, (dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)>`

error[E0277]: expected a `std::ops::FnOnce<(std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)>,)>` closure, found `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)`
  --> api-server\src\db\sessions.rs:32:6
   |
32 | impl ::actix_web::FromRequest for Box<dyn SessionRepository> {
   |      ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)>,)>` closure, found `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)`
   |
   = help: the trait `std::ops::FnOnce<(std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)>,)>` is not implemented for `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)`
   = note: required because of the requirements on the impl of `core::future::future::Future` for `futures_util::future::try_future::map_ok::MapOk<futures_util::future::ready::Ready<std::result::Result<std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)>, actix_web::Error>>, (dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)>`

error[E0277]: the size for values of type `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)` cannot be known at compilation time
  --> api-server\src\db\sessions.rs:34:5
   |
34 | /     type Future = ::futures::future::MapOk<
35 | |         ::futures::future::Ready<Result<Self, Self::Error>>,
36 | |         FnOnce(RealSessionRepository) -> Box<(dyn SessionRepository + 'static)>,
37 | |     >;
   | |______^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required by `futures_util::future::try_future::map_ok::MapOk`

error[E0277]: the size for values of type `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)` cannot be known at compilation time
  --> api-server\src\db\sessions.rs:40:5
   |
40 | /     fn from_request(
41 | |         req: &::actix_web::HttpRequest,
42 | |         payload: &mut actix_web::dev::Payload,
43 | |     ) -> Self::Future {
44 | |         RealSessionRepository::from_request(&req, payload).map_ok(|dep| Box::new(dep))
45 | |     }
   | |_____^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce(db::sessions::RealSessionRepository) -> std::boxed::Box<(dyn db::sessions::SessionRepository + 'static)> + 'static)`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
   = note: required by `futures_util::future::try_future::map_ok::MapOk`

MRE 可在:https://github.com/zlepper/actix_web_mre 因为它需要 actix,而 actix 在 rust 操场上不可用。

这特别是关于当我想要一个关联类型中的动态特征引用时如何处理这个问题,我不拥有它,因此不能做很多改变。更具体地说,我将如何使用 FnOnce 执行此操作,其中实际实现仅在编译时生成(我认为)。

我知道我可以稍微缩短类型定义,使它们不完全限定,但这是我想使用宏生成的东西,据我所知最好使用完整类型。

有没有更好的方法来输入 return 未来?现在的定义挺毛的。。

FnOnce 是一个特征,因此在编译时没有已知的大小。然而,我们可以将它包装在一个已知大小的 Box 中,以使其编译:

impl ::actix_web::FromRequest for Box<dyn SessionRepository> {
    type Error = ::actix_web::Error;
    type Future = ::futures::future::MapOk<
        ::futures::future::Ready<Result<RealSessionRepository, Self::Error>>,
        Box<dyn FnOnce(RealSessionRepository) -> Box<(dyn SessionRepository)>>,
    >;
    type Config = ();

    fn from_request(
        req: &::actix_web::HttpRequest,
        payload: &mut actix_web::dev::Payload,
    ) -> Self::Future {
        RealSessionRepository::from_request(&req, payload).map_ok(Box::new(|dep| Box::new(dep)))
    }
}