【问题标题】:How do I generify the error of a Rust Result<T, E> to Result<T, Box<dyn std::error::Error>>?如何将 Rust Result<T, E> 的错误生成为 Result<T, Box<dyn std::error::Error>>?
【发布时间】:2021-07-04 21:28:31
【问题描述】:

我正在尝试生成由reqwest::blocking::get 函数返回的Result。它返回一个Result&lt;reqwest::blocking::Response, reqwest::Error&gt;,但调用它的函数返回一个Result&lt;reqwest::blocking::Response, Box&lt;dyn std::error::Error&gt;

  • 为什么我的第一次尝试编译失败?
  • 进行这种转换最惯用的方法是什么?

这是第一次尝试:

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)),
        }
    }

【问题讨论】:

    标签: rust reqwest rust-result


    【解决方案1】:

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

    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&lt;dyn Error&gt;,它向编译器表明该值应该被向下转换,并且应该删除Box中的具体reqwest::Error这一事实。

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

    【讨论】:

    • “但你想要的是dyn Error 的特征对象,Box&lt;reqwest:Error&gt; 可能是”我不同意。您可以从Box&lt;reqwest:Error&gt;创建Box&lt;dyn Error&gt;,但Box&lt;reqwest:Error&gt; 不能成为(或“用作”等)@987654345 @(例如,因为 Box&lt;reqwest:Error&gt; 内部只包含一个指针,但 Box&lt;dyn Error&gt; 包含两个)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 2020-10-08
    • 2020-06-20
    • 2020-03-26
    相关资源
    最近更新 更多