2016-03-23 4 views
4

У меня проблема с реализацией черты Error. Я хочу обернуть ошибку от Diesel или другого драйвера базы данных. Я даже не приблизился к внедрению From, так как я уже не выполняю Error. Строка, которая заставляет код не компилироваться, - это тот, который находится в самом конце блока кода.Как реализовать 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), 
     } 
    } 
} 

Я также попытался:

*cause does not live long enough

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

the trait core::marker::Sized is not implemented for the type std::error::Error + Send + Sync + 'static [E0277]

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

the trait std::error::Error is not implemented for the type `&Box

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

Но ни один из них не работал.

ответ

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), 
} 
Смежные вопросы