Как сделать ошибки цепочки ошибок совместимыми с ошибками ошибок? - PullRequest
0 голосов
/ 14 мая 2018

С учетом следующего кода:

extern crate dotenv; // v0.11.0
#[macro_use]
extern crate failure; // v0.1.1

#[derive(Debug, Fail)]
#[fail(display = "oh no")]
pub struct Error(dotenv::Error);

Из-за того факта, что error-chain (последняя версия v0.11) не гарантирует, что его ошибкой является Sync ( открытый PR для устранения проблемы ), я получаю сообщение об ошибке, что Sync не реализовано для dotenv::Error:

error[E0277]: the trait bound `std::error::Error + std::marker::Send + 'static: std::marker::Sync` is not satisfied
 --> src/main.rs:5:17
  |
5 | #[derive(Debug, Fail)]
  |                 ^^^^ `std::error::Error + std::marker::Send + 'static` cannot be shared between threads safely
  |
  = help: the trait `std::marker::Sync` is not implemented for `std::error::Error + std::marker::Send + 'static`
  = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<std::error::Error + std::marker::Send + 'static>`
  = note: required because it appears within the type `std::boxed::Box<std::error::Error + std::marker::Send + 'static>`
  = note: required because it appears within the type `std::option::Option<std::boxed::Box<std::error::Error + std::marker::Send + 'static>>`
  = note: required because it appears within the type `error_chain::State`
  = note: required because it appears within the type `dotenv::Error`
  = note: required because it appears within the type `Error`

Какое минимальное количество шаблонов / работ, которые я могу выбрать, чтобы эти типы хорошо играли вместе? Самое короткое, что я смог придумать, - это добавление нового типа ErrorWrapper, чтобы я мог реализовать Error на Arc<Mutex<ERROR_CHAIN_TYPE>>:

use std::fmt::{self, Debug, Display, Formatter};
use std::sync::{Arc, Mutex};

#[derive(Debug, Fail)]
#[fail(display = "oh no")]
pub struct Error(ErrorWrapper<dotenv::Error>);

#[derive(Debug)]
struct ErrorWrapper<T>(Arc<Mutex<T>>)
where
    T: Debug;

impl<T> Display for ErrorWrapper<T>
where
    T: Debug,
{
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "oh no!")
    }
}

impl<T> ::std::error::Error for ErrorWrapper<T>
where
    T: Debug,
{
    fn description(&self) -> &str {
        "whoops"
    }
}

// ... plus a bit more for each `From<T>` that needs to be converted into
// `ErrorWrapper`

Это правильный путь? Есть ли что-то, что будет стоить меньше кода / времени выполнения для преобразования в Arc<Mutex<T>> для вещей, которые в этом не нуждаются?

1 Ответ

0 голосов
/ 14 мая 2018

Единственное, что я могу предложить, - это удалить тип Arc.

Если у вас есть что-то, что не Sync, то оберните в тип Mutex, чтобы интегрировать error-chainс failure просто заверните dotenv::Error:

#[macro_use]
extern crate failure;
extern crate dotenv;
use std::sync::Mutex;

#[derive(Debug, Fail)]
#[fail(display = "oh no")]
pub struct Error(Mutex<dotenv::Error>);

fn main() {
    match dotenv::dotenv() {
        Err(e) => {
            let err = Error(Mutex::new(e));
            println!("{}", err)
        }
        _ => (),
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...