courses/dss/raft/src/raft/mod.rs 编译出错:the `map_err` method cannot be invoked on a trait object

尝试做 courses/dss/raft test_2a,将 Raft::send_request_vote 方法中的注释解开,期望能正常调用RPC。 以下是 send_request_vote 的代码:

    fn send_request_vote(
        &self,
        server: usize,
        args: &RequestVoteArgs,
    ) -> Receiver<Result<RequestVoteReply>> {
        // Your code here if you want the rpc becomes async.
        // Example:
        // ```
        // let peer = &self.peers[server];
        // let (tx, rx) = channel();
        // peer.spawn(
        //     peer.request_vote(&args)
        //         .map_err(Error::Rpc)
        //         .then(move |res| {
        //             tx.send(res);
        //             Ok(())
        //         }),
        // );
        // rx
        // ```
        let (tx, rx) = sync_channel::<Result<RequestVoteReply>>(1);
        // crate::your_code_here((server, args, tx, rx))
        let peer = &self.peers[server];
        peer.spawn(
            peer.request_vote(&args)
                .map_err(Error::Rpc)
                .then(move |res| {
                    tx.send(res);
                    Ok(())
                }),
        );
        rx
    }

自己理解没有错的话,peer.request_vote 语句调用的是 raft/src/proto/mod.rs:6 中的代码

pub mod raftpb {
    include!(concat!(env!("OUT_DIR"), "/raftpb.rs"));

    labrpc::service! {
        service raft {
            rpc request_vote(RequestVoteArgs) returns (RequestVoteReply);
            rpc heart_beat(AppendEntriesArgs) returns (AppendEntriesReply);

            // Your code here if more rpc desired.
            // rpc xxx(yyy) returns (zzz)
        }
    }
    pub use self::raft::{
        add_service as add_raft_service, Client as RaftClient, Service as RaftService,
    };
}
  • request_vote 方法 return 的对象是 RpcFuture,也就是一个 Box 包装过的 FutureFuture 本身是有这个 map_err 方法的。
  • raft/mod.rs 也引入了 use labrpc::RpcFuture;
  • 整个 RPC 调用逻辑,我并没有做修改。只修改了以下文件
    • dss/raft/src/raft/mod.rs
    • dss/raft/src/proto/raft.proto
    • dss/raft/src/proto/mod.rs

问题

执行命令 make test_2a 后,报错:

cargo fmt --all -- --check
cargo clippy --all --tests -- -D clippy::all
    Checking raft v0.1.0 (/Users/asiafrank/workspace/pingcap-talent-plan-learning/dss/raft)
error: the `map_err` method cannot be invoked on a trait object
   --> raft/src/raft/mod.rs:208:18
    |
208 |                 .map_err(Error::Rpc)
    |                  ^^^^^^^
    | 
   ::: /Users/asiafrank/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.27/src/future/mod.rs:412:21
    |
412 |               Self: Sized,
    |                     ----- this has a `Sized` requirement
    |
    = note: another candidate was found in the following trait, perhaps add a `use` for it:
            `use crate::proto::raftpb::raft::__futures::Future;`
error: aborting due to 2 previous errors

error: could not compile `raft`.

To learn more, run the command again with --verbose.
make: *** [check] Error 101

求助各位大神,这个问题出现的原因是什么,怎么解决?

尝试添加一行

use futures::Future; 

或者添加一行(如果使用的是最新的 master,> https://github.com/pingcap/talent-plan/commit/4c74c3653fd4bb3388138e2d4260a44dc9f2a131)

use futures::future::FutureExt;

谢谢,使用 use futures::Future; 编译能过了。