A 有一个函数,该函数在 Option<> 类型中不编译,但在 Option<> 类型之外自行编译。为什么?

  • 本文关键字:类型 编译 Option 函数 有一个 但在 rust
  • 更新时间 :
  • 英文 :


我有这个函数:

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:UsersFred.rustuptoolchainsstable-x86_64-pc-windows-msvclib/rustlib/src/rustlibrarycoresrcresult.rs:508:5
|
508 |     Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
|     ^^

但如果我删除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>)。

有几种方法可以解决这个问题。您可以尝试注释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 _),但我不确定这是否适用于这种情况。

相关内容

最新更新