0

我有以下 actix_webFromRequest特征的实现:

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))
    }
}

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

RealSessionRepository::from_request返回一个未来,也是该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,而在 rust 操场上不可用。

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

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

有没有更好的方法来输入未来的回报?目前的定义是相当毛茸茸的..

4

1 回答 1

1

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)))
    }
}
于 2020-01-03T17:43:49.430 回答