在尝试打开具体的错误类型时,为什么我的错误必须对静态生命周期有效?

时间:2018-01-02 00:22:59

标签: rust

我正在尝试实现一个简单的模式:如果我有一些错误,我可以尝试恢复我的应用程序,否则我只是将此异常弹出给调用者:

use std::error::Error;

fn main() {
    let _ = sample();
}

fn sample() -> std::result::Result<i32, std::io::Error> {
    let result: Result<i32, std::io::Error> = Ok(10); // performing some operation
    match result {
        Ok(x) => Ok(x + 1),
        Err(e) => match e.cause() {
            // if it has any error
            Some(cause) => {
                // and it has any cause
                let io_error = cause.downcast_ref::<std::io::Error>(); // and this cause is IO error
                match io_error {
                    Some(_) => Ok(547), // return default value
                    None => Err(e),     // otherwise return an error
                }
            }
            None => Err(e),
        },
    }
}

如果操作成功,我想返回x+1。如果没有,但它是由io::Error引起的,则返回547。如果它是由其他原因造成的,那么只需按原样返回错误。

当前的编译器错误是:

error[E0597]: `e` does not live long enough
  --> src\main.rs:11:25
   |
11 |         Err(e) => match e.cause() { // if it's caused
   |                         ^ borrowed value does not live long enough
...
21 |     }
   |     - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

我不明白为什么它说它必须有static有效期......

2 个答案:

答案 0 :(得分:3)

确实,编译器is not more explicit

是不幸的

让我放松一下:

  1. Error::downcast_ref仅针对Error + 'static实施(因此,当self生命周期本身为'static时),
  2. 因此,在cause.downcast_ref中,cause必须为'static
  3. Error::cause将其结果的生命周期与self
  4. 的生命周期联系起来
  5. 因此,在e.cause()中,e必须为'static
  6. eErr(e)中引入的临时内容。
  7. 希望这更清楚。

    我还没有使用它,但Rust核心团队成员之一(无船)一直在研究一个新的failure crate,据说可以解决Error用法的一些问题。

答案 1 :(得分:2)

因为那是requirement of the function you are using

impl Error + 'static {
    pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T>
}

您无法向下转换非'static的特征对象。

可以进一步减少示例代码,使其更加清晰。注释掉downcast_ref可以编译代码:

fn example(result: Result<i32, std::io::Error>) -> Result<i32, std::io::Error> {
    let e = result.unwrap_err();
    let cause = e.cause().unwrap();
    let _io_error = cause.downcast_ref::<std::io::Error>();
    unimplemented!()
}

这可能只是您缩减的示例代码的工件,但我不明白您为什么要使用Result<_, std::io::Error>并检查io::Error的原因是否另一个 io::Error。如果您的ResultErr,那么您知道 io:Error,因为这是唯一可能的事情。 io::Error doesn't even provide a cause,除非您使用自定义错误变体。

另见: