rust - 尝试使用 dyn AsyncReadExt, "the trait cannot be made into an object"错误

标签 rust rust-cargo rust-tokio

我正在开发旨在与 TcpStream 或 stdin/stdout 一起使用的网络服务。我得到一个编译错误:the trait tokio::io::util::async_read_ext::AsyncReadExt cannot be made into an object .目前我的解决方法是使用包装枚举:

enum ClientReader {
    Stream(OwnedReadHalf),
    Stdin(Stdin),
}

enum ClientWriter {
    Stream(OwnedWriteHalf),
    Stdout(Stdout),
}
这需要 match到处都是 block ,看起来很不雅。
我做了一个简化的项目来重现这个问题:
cargo .toml
[package]
name = "demo"
version = "0.1.0"
authors = ["test"]
edition = "2018"

[dependencies]
tokio = { version = "0.2", features = ["full"] }
src/main.rs
use tokio::io::AsyncReadExt;

struct Test {
  test: Box<dyn AsyncReadExt>,
}

fn main () {}
这会产生类似的错误:
error[E0038]: the trait `tokio::io::AsyncReadExt` cannot be made into an object
    --> src/main.rs:4:3
     |
4    |   test: Box<dyn AsyncReadExt>,
     |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `tokio::io::AsyncReadExt` cannot be made into an object
     |
    ::: /home/???/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.22/src/io/util/async_read_ext.rs:162:12
     |
162  |         fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>
     |            ---- the trait cannot be made into an object because method `read` references the `Self` type in its return type
...
280  |         fn read_exact<'a>(&'a mut self, buf: &'a mut [u8]) -> ReadExact<'a, Self>
     |            ---------- the trait cannot be made into an object because method `read_exact` references the `Self` type in its return type
我不确定如何进行。我在考虑一个巨人 impl enum 的 block 包装器,但这似乎比 match block 。在 OO 语言中会有一个父类或接口(interface),所以我调查了 trait_enum自动制作包装器的 crate impl但是让它发挥作用有很多麻烦。
目前,我确定唯一可行的清理方法是将解决方法移动到宏或函数中。
我将不胜感激有关更好方法的任何反馈。 :)
编辑:根据 user4815162342 的建议,我将结构泛型设置为 AsyncReadExt这似乎适用于我的示例。稍后将尝试我的更大项目。
use tokio::io::AsyncReadExt;

struct Test<T: AsyncReadExt> {
  test: T,
}

async fn myfn<T: AsyncReadExt>(mut t: Test<T>) where T: std::marker::Unpin {
    let mut v = Vec::<u8>::new();
    t.test.read_buf(&mut v).await;
}

fn main () {}

最佳答案

AsyncRead到一个 trait 对象,你应该使用类型 Pin<Box<dyn AsyncRead>> .

use std::pin::Pin;
use tokio::io::AsyncRead;

struct Test {
    test: Pin<Box<dyn AsyncRead>>,
}

impl Test {
    fn new<T: AsyncRead>(io: T) -> Self {
        Self {
            test: Box::pin(io),
        }
    }
}
AsyncReadExt trait 是一个扩展 trait,你应该总是使用 AsyncRead提及 AsyncRead 的类型时的特征.

关于rust - 尝试使用 dyn AsyncReadExt, "the trait cannot be made into an object"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63626508/

相关文章:

vim - 使用 Rust-analyzer 处理单个文件 Rust

linux - 我们如何为同一台 Linux 机器上的所有用户安装 rustc、cargo?

rust - 如何将编译期间命令行上提供的字符串编译成我的 Rust 二进制文件?

sockets - 如何将Tokio设置为多线程UDP服务器?

async-await - 如何使用 Rust 中新的异步等待语法通过 H2 执行 HTTP2 请求?

rust - 不可变值仍在移动

rust - 为什么cloned()允许这个函数编译

rust - 无法 tokio::run 盒装 Future,因为不满足特征绑定(bind) Send

rust - 调用从 Wasmtime 返回字符串的 WASM 函数

rust - 本地拥有的引用资料被认为是借来的