How do I generify the error of a Rust Result<T, E> to Result<T, Box<dyn std::error::Error>>?

How do I generify the error of a Rust Result<T, E> to Result<T, Box<dyn std::error::Error>>?

我正在尝试生成由 reqwest::blocking::get 函数返回的 Result。它returns一个Result<reqwest::blocking::Response, reqwest::Error>但是它在returns一个Result<reqwest::blocking::Response, Box<dyn std::error::Error>.

中调用的函数

这是第一次尝试:

fn get_example_fails() -> Result<Response, Box<dyn Error>> {
        let result = blocking::get("http://example.com");
        result.map_err(|error| Box::new(error))
    }

它有以下错误,我不知道如何修复,但觉得通过一些小的调整可能更符合习惯 - 但我不确定要调整什么:

error[E0308]: mismatched types
   --> src/bittrex.rs:143:9
    |
141 |     fn get_example_fails() -> Result<Response, Box<dyn Error>> {
    |                               -------------------------------- expected `Result<reqwes
t::blocking::Response, Box<(dyn StdError + 'static)>>` because of return type
142 |         let result = blocking::get("http://example.com");
143 |         result.map_err(|error| Box::new(error))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn StdError`, 
found struct `reqwest::Error`
    |
    = note: expected enum `Result<_, Box<(dyn StdError + 'static)>>`
               found enum `Result<_, Box<reqwest::Error>>`

此尝试编译但似乎冗长:

fn get_example_works() -> Result<Response, Box<dyn Error>> {
        let result = blocking::get("http://example.com");
        match result {
            Ok(resp) => Ok(resp),
            Err(error) => Err(Box::new(error)),
        }
    }

这是因为编译器在这里过于热心了。请注意 Box::new(error) 只是将 error 放入 Box 中,因此您会得到一个强类型的 Box<reqwest:Error>,正如编译器报告的那样。但是你想要的是 dyn Error 的特征对象,Box<reqwest:Error> 可能是,但编译器不会做出这种类型弱化假设。修复是手动明确的:

fn get_example_fails() -> Result<Response, Box<dyn Error>> {
        let result = blocking::get("http://example.com");
        result.map_err(|error| Box::new(error) as Box<dyn Error>)
}

注意额外的 as Box<dyn Error>,它向编译器表明该值应该向下转换,并且它是 Box 中的具体 reqwest::Error 的事实应该被删除。

第二个示例编译良好的原因是类型推断。在第一个示例中,从函数中编辑的 return 类型将是从 .map_err() 中编辑的类型 return,即 Result<Response, Box<reqwest::Error>> - 就是这样。类型不匹配,所以你得到一个错误。在第二个例子中,match 构造了一个全新的 Result 并且 Rust 必须为此推断出 TE;所以类型推断开始了。在第二种情况下,由于函数的 return 值的推断相对于 Box<dyn Error> 是成功的。但是对于 map_err(),类型推断不能“调查”map_err()-body 并弱化 它是 return 类型;已经太晚了,类型是固定的。这就是为什么您必须按照上面的建议手动执行此操作的原因。