如何将 Box<dyn Error + Sync + Send> 转换为 Box<dyn Error>

Posted

技术标签:

【中文标题】如何将 Box<dyn Error + Sync + Send> 转换为 Box<dyn Error>【英文标题】:How to convert Box<dyn Error + Sync + Send> to Box<dyn Error> 【发布时间】:2020-03-26 14:16:52 【问题描述】:

在我的程序中,在辅助线程上执行了一些操作及其结果:Result&lt;(), Box&lt;dyn Error&gt;&gt; 被发送回主线程。对于具有Send 要求的错误来说,这是非常合理的,因此实际类型是Result&lt;(), Box&lt;dyn Error + Send&gt;&gt;。我还添加了Sync 以便能够使用Box from 方法(仅针对普通或同步+发送实现)。但是在单线程上解决结果后,我想放弃这个要求。

例子:

use std::error::Error;

fn test1() -> Result<(), Box<dyn Error + Sync + Send>> 
    return Err("test1".into());

fn test2() -> Result<(), Box<dyn Error>> 
    test1()?;
    return Ok(());

fn main() 
    let test2_result = test2();
    println!("test2_result: :#?", test2_result);

最后我实际上是这样结束的:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the size for values of type `dyn std::error::Error + std::marker::Send + std::marker::Sync` cannot be known at compilation time
 --> src/main.rs:7:12
  |
7 |     test1()?;
  |            ^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `dyn std::error::Error + std::marker::Send + std::marker::Sync`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>`
  = note: required because of the requirements on the impl of `std::convert::From<std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>` for `std::boxed::Box<dyn std::error::Error>`
  = note: required by `std::convert::From::from`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

这些类型似乎不兼容。

那么我怎样才能将(例如在test2Result&lt;(), Box&lt;dyn Error + Send&gt;&gt; 转换为Result&lt;(), Box&lt;dyn Error&gt;&gt;

我知道这可以通过创建包装器来完成,但我不想添加下一级间接。

【问题讨论】:

if let Err(e) = test1() return Err(e); 可以工作。 看来向上转换 trait 对象是个问题,见***.com/questions/28632968/… 【参考方案1】:

如何在这两种类型之间转换的问题仍然悬而未决。

现在我切换到https://crates.io/crates/failure crate 进行错误处理,其中Error 类型替换Box&lt;dyn Error + Sync + Send&gt;,也可以轻松创建自定义和字符串(甚至格式化)错误。

【讨论】:

以上是关于如何将 Box<dyn Error + Sync + Send> 转换为 Box<dyn Error>的主要内容,如果未能解决你的问题,请参考以下文章

Box<dyn Trait> doesn‘t implement the trait

Box<dyn Trait> doesn‘t implement the trait

如何将 Rc<RefCell<dyn T>> 传递给想要 &dyn T 的 fn?

rust - 方法 `draw`存在,但在Vec <Box <dyn Trait >>中不满足以下特征范围,Compilernote应该满足吗?

virtual box启动error

如何将盒装切片 (`Box<[T]>`) 传递给 C 函数?