我有这个功能:
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),
| ^^
但是如果我去掉Option<>
部分就可以了,为什么?
1条答案
按热度按时间plicqrtu1#
从本质上讲,您的问题可以归结为为什么其中一个函数可以编译,而另一个不能:
这里的关键是
Box<T>
和Box<dyn Trait>
是具有不同内存表示的不同类型,即使T
实现了Trait
。但是,当Box
在另一个类型中时,由于它现在是非基元强制转换,因此无法执行此操作(这就像为什么不能将Option<u8>
转换为Option<u16>
一样)。有几种方法可以解决这个问题。你可以尝试注解
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 _)
,但是我不确定这是否适用于这种情况。