0

我正在尝试生成函数Result返回的a reqwest::blocking::get。它返回 aResult<reqwest::blocking::Response, reqwest::Error>但调用它的函数返回 a 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)),
        }
    }
4

1 回答 1

0

这是因为编译器在这里过于热心。请注意,就像编译器报告的那样,Box::new(error)只需放入errora Box,您就会得到一个强类型的 。Box<reqwest:Error>但是你想要的是一个 trait 对象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>)
}

注意 extra as Box<dyn Error>,它使编译器清楚地知道该值应该被向下转换,并且它是一个具体的事实reqwest::Error应该Box被删除。

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

于 2021-07-04T21:43:24.333 回答