用于多个错误处理的impl trait

时间:2017-09-05 18:57:08

标签: rust

有可能做这样的事吗?如果不是为什么?

use std::error::Error;
use std::io::{self, Read};

fn main() {
    if let Err(e) = foo() {
        println!("Error: {}", e);
    }
}

fn foo() -> Result<(), impl Error> {
    let mut buffer = String::new();
    io::stdin().read_to_string(&mut buffer)?;
    let _: i32 = buffer.parse()?;
    Ok(())
}

我收到此错误:

error[E0282]: type annotations needed
  --> src/main.rs:10:24
   |
10 | fn foo() -> Result<(), impl Error> {
   |                        ^^^^^^^^^^ cannot infer type for `_`

1 个答案:

答案 0 :(得分:8)

这里有两个问题:

  1. impl Traits在编译时静态解析为具体类型。在这里,您尝试返回实现Error的两种不同类型:std::io::Errorstd::num::ParseIntError。由于在编译期间必须将impl Trait解析为只有一种类型,因此无法做到这一点。

  2. ?运算符调用From::from以在错误类型之间进行转换,这意味着它在目标类型方面具有灵活性。这里,目标类型是impl Trait,因此编译器没有足够的信息来知道选择哪种确切类型。

  3. 由于这些原因,impl Traits并不是真正适合在此使用的工具。您可以通过以下方式解决此问题:

    • 使用Box<dyn Error>作为返回类型。这为From<E>类型实现了Error,因此转换将自动生效。但它需要动态分配。
    • 将新错误类型实现为枚举,该枚举可以包含函数返回的任何错误类型,并为每种类型实现From<ErrType>