【问题标题】:How to make error-chain errors compatible with Failure errors?如何使错误链错误与失败错误兼容?
【发布时间】:2018-05-13 22:59:08
【问题描述】:

给定以下代码:

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,最新版本)不能保证它的包装错误是Syncopen PR to fix the issue),我收到一条错误消息,指出Sync 没有为@987654326 实现@:

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 newtype,这样我就可以在Arc&lt;Mutex&lt;ERROR_CHAIN_TYPE&gt;&gt; 上实现Error

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&lt;Mutex&lt;T&gt;&gt;

【问题讨论】:

    标签: error-handling rust


    【解决方案1】:

    我唯一能建议的就是删除 Arc 类型。

    如果你有一些不是 Sync 的东西,那么包装成 Mutex 类型,所以 将error-chainfailure 整合,只需包装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)
            }
            _ => (),
        }
    }
    

    【讨论】:

    • 感谢@E_net4 的反馈!
    • 这很好,我不需要Arc,因为我实际上并没有分享价值,只是发送它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    • 2019-10-01
    • 2016-11-09
    • 2011-09-06
    • 2018-06-13
    • 1970-01-01
    • 2016-01-19
    相关资源
    最近更新 更多