如何正确实现Error :: cause?

时间:2016-03-23 17:27:02

标签: reference rust option traits

我在实现Error特征方面遇到了问题。我想从Diesel或其他数据库驱动程序中包装错误。我甚至没有接近实施From,因为我已经无法实施Error。导致代码无法编译的行是代码块最后的那一行。

use std::fmt;
use std::error::{self, Error};

#[derive(Debug)]
pub enum MyError {
    NotFound(String),
    PersistenceError(Box<Error + Send + Sync>),
}

pub type MyResult<T> = Result<T, MyError>;

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MyError::NotFound(ref msg) => write!(f, "Not found: {}", msg),
            MyError::PersistenceError(ref cause) => write!(f, "Persistence error: {}", cause),
        }
    }
}

impl Error for MyError {
    fn description(&self) -> &str {
        match *self {
            MyError::NotFound(ref msg) => msg,
            MyError::PersistenceError(ref cause) => cause.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            MyError::NotFound(_) => None,
            // `*cause` does not live long enough
            MyError::PersistenceError(cause) => Some(&*cause),
        }
    }
}

我也尝试过:

  

*因为活得不够长

MyError::PersistenceError(cause) => Some(&*cause),
  

该类型没有实现trait core :: marker :: Sized   std :: error ::错误+发送+同步+&#39;静态[E0277]

MyError::PersistenceError(ref cause) => Some(cause),
  

trait std :: error ::类型`&amp; Box

没有实现错误
MyError::PersistenceError(ref cause) => Some(&cause)

但这些都没有奏效。

1 个答案:

答案 0 :(得分:6)

对于print the type of variables这样的情况很有用:

match *self {
    MyError::NotFound(_) => None,
    MyError::PersistenceError(ref cause) => {
        let () = cause;
    },
}

这会告诉您cause&Box<std::error::Error + Send + Sync>

如果我们取消引用一次,我们会有一个Box<std::error::Error + Send + Sync>,如果我们第二次取消引用它,我们会有一个std::error::Error + Send + Sync(这不是真正的类型)。然后我们可以采用另一个可以隐含地构成&Error

的引用
match *self {
    MyError::NotFound(_) => None,
    MyError::PersistenceError(ref cause) => Some(&**cause),
}