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

问题描述 投票:0回答:2

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

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一生......

rust
2个回答
3
投票

确实,编译器is not more explicit是不幸的。

让我放松一下:

  1. Error::downcast_ref仅适用于Error + 'static(因此,当self的生命本身为'static时),
  2. 因此在cause.downcast_refcause必须是'static
  3. Error::cause将其结果的生命周期与self的结果联系起来,
  4. 因此在e.cause()e必须是'static
  5. e是在Err(e)临时引入的。

希望这更清楚。


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


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。如果你的Result是一个Err,那么你知道这是一个io:Error,因为它是唯一可能的事情。 io::Error doesn't even provide a cause,除非您使用自定义错误变体。

也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.