我有这个功能:

pub async fn player(&self, id: &str) -> Result<Option<Box<dyn AsyncRead + Send>>> {
    // use id here...
    let file = tokio::fs::File::open("player.pdf").await?;
    let res = Some(Box::new(file));
    Ok(res)
}

它不起作用:

error[E0308]: mismatched types
    |
46  |         Ok(res)
    |         -- ^^^ expected trait object `dyn tokio::io::AsyncRead`, found struct `tokio::fs::File`
    |         |
    |         arguments to this enum variant are incorrect
    |
    = note: expected enum `std::option::Option<std::boxed::Box<dyn tokio::io::AsyncRead + std::marker::Send>>`
               found enum `std::option::Option<std::boxed::Box<tokio::fs::File>>`
note: tuple variant defined here
   --> C:\Users\Fred\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\result.rs:508:5
    |
508 |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^

但如果我go 掉Option<>的部分就行了.为什么?

推荐答案

从本质上讲,您的问题可以归结为为什么这些函数中的一个可以编译,而另一个不能:

fn compiles() -> Box<dyn std::fmt::Debug> {
    let b: Box<&str> = Box::new("foo");
    b
}

fn doesnt_compile() -> Option<Box<dyn std::fmt::Debug>> {
    let b: Option<Box<&str>> = Some(Box::new("foo"));
    b
}

这里的关键是,Box<T>Box<dyn Trait>是具有不同内存表示的不同类型,即使T实现Trait.通常,Rust很乐意隐式地将Box<T>强制转换为Box<dyn Trait>,但是当Box位于另一个类型中时,就不能这样做了,因为它现在是一个非原语强制转换(这就是为什么您不能将Option<u8>强制转换为Option<u16>).

有几种方法可以解决这个问题.您可以try 对res(let res: Option<Box<dyn AsyncRead + Send>> = ...)进行注释,或对Box::new(let res = Some(Box::new(file) as Box<dyn AsyncRead + Send>))的结果进行强制转换.在许多情况下,也可以完全省略类型,只编写let res = Some(Box::new(file) as _),但我不确定这是否适用于这种情况.

Rust相关问答推荐

计算具有相邻调换且没有插入或删除的序列的距离

如何优化小型固定大小数组中的搜索?

空字符串转换为Box字符串时是否分配?<>

如何点击()迭代器?

无法从流中读取Redis请求

Rust 的多态现象.AsRef与Derf

链表堆栈溢出

Rust从关联函数启动线程

为什么`tokio::main`可以直接使用而不需要任何导入?

Rust:为什么 &str 不使用 Into

Rust LinkedList 中的borrow 判断器错误的原因是什么?

Nom 解析器无法消耗无效输入

.to_owned()、.clone() 和取消引用 (*) 之间有区别吗?

更新 rust ndarray 中矩阵的一行

Option<&T> 如何实现复制

在Rust中实现Trie数据 struct 的更好方式

有没有办法通过命令获取 Rust crate 的可安装版本列表?

在 Rust 中,为什么整数溢出有时会导致编译错误或运行时错误?

为什么 i32 Box 类型可以在 Rust 中向下转换?

从现有系列和 map 值创建新系列