为什么编译器说该参数没有实现所需的特征?

Why compiler says that argument doesn't implement required traits?

不久前我开始学习 Rust 语言,现在我正在为个人项目实现一个 websocket 服务器。话虽如此,我不是专业的 Rust 程序员,我仍处于学习基础知识的阶段。

我用三个库开发这个项目,tokiohypertokio-tungstenite。我的 HTTP 服务器是用 hyper 编写的。基本上只有一个处理程序。此处理程序做一件事,将传入的 UPGRADE HTTP 请求升级为 WebSocket 连接。

use std::str;

use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::prelude::*;

use hyper::header::{HeaderValue, UPGRADE, SEC_WEBSOCKET_ACCEPT};
use hyper::service::{make_service_fn, service_fn};
use hyper::upgrade::Upgraded;
use hyper::{Body, Client, Request, Response, Server, StatusCode};
use std::net::SocketAddr;

// A simple type alias so as to DRY.
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

async fn server_upgrade(req: Request<Body>) -> Result<Response<Body>> {
    let mut res = Response::new(Body::empty());

    // Send a 400 to any request that doesn't have
    // an `Upgrade` header.
    if !req.headers().contains_key(UPGRADE) {
        *res.status_mut() = StatusCode::BAD_REQUEST;
        return Ok(res);
    }

    // Setup a future that will eventually receive the upgraded
    // connection and talk a new protocol, and spawn the future
    // into the runtime.
    //
    // Note: This can't possibly be fulfilled until the 101 response
    // is returned below, so it's better to spawn this future instead
    // waiting for it to complete to then return a response.
    let upgraded: Upgraded = match req.into_body().on_upgrade().await {
      Ok(upgraded) => upgraded,
      Err(e) => {
        eprintln!("upgrade error: {}", e);
        return Err(Box::new(e));
      },
    };
    tokio_tungstenite::accept_async(upgraded);
    Ok(res)
}

在最后第 3 行,编译器发出一条错误消息:

the trait bound `hyper::upgrade::Upgraded: tokio::io::async_read::AsyncRead` is not satisfied
the trait `tokio::io::async_read::AsyncRead` is not implemented for `hyper::upgrade::Upgraded`

the trait bound `hyper::upgrade::Upgraded: tokio::io::async_write::AsyncWrite` is not satisfied
the trait `tokio::io::async_write::AsyncWrite` is not implemented for `hyper::upgrade::Upgraded`

但是当我查看 hyper::upgrade::Upgraded, I can see that it actually implements those traits. As I also look at the tokio-tunsgstenite 的文档时,确实这些特征是来自同一个板条箱的相同特征。

有经验的 rustecean 能帮我解决这个问题并让编译器相信 upgraded 实例实现了相同的特征吗?也许板条箱之间的版本不匹配?

我还附上了我的 Cargo.toml 文件。

[package]
name = "async-rs"
version = "0.1.0"
authors = ["Bora Semiz <Bora Semiz's email address>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hyper = "0.13.9"
tokio = { version = "^0.2", features = ["full"] }
tokio-tungstenite = "0.12.0"

Hyper 使用的是 Tokio 版本 0.2.x,而 tokio-tungstenite 使用的是 Tokio 版本 0.3.x。从 Tokio 0.20.3 的变更日志包括对 AsyncReadAsyncWrite 特性的重大更改,使这两个特性与其版本 0.2 不兼容。

您可以使用 tokio_compat_02 crate 连接两者,直到 Hyper 发布新版本(同时将您自己的 tokio 版本升级到 Cargo.toml 中的 0.3),或者将 tokio-tungstenite 降级为 0.11.0,如果您愿意,它使用 tokio 0.2.x