12

In my program some actions are performed on secondary thread and their results: Result<(), Box<dyn Error>> are sent back to primary thread. This is pretty reasonable for errors to have Send requirement, so the actual type is Result<(), Box<dyn Error + Send>>. I also added Sync to be able to use Box from method (which is implemented for plain or Sync + Send only). But after result is settled on single thread I want to drop this requirement.

Example:

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);
}

In the end I actually end with:

   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.

It seems those types are not compatible.

So how can I convert (for example in test2) Result<(), Box<dyn Error + Send>> to Result<(), Box<dyn Error>>?

I know this can be done by creating a wrapper, but I don't want to add next level of indirection.

peku33
  • 3,628
  • 3
  • 26
  • 44
  • A `if let Err(e) = test1() { return Err(e);}` will work. – CoronA Dec 02 '19 at 04:51
  • 1
    It seems that upcasting trait objects is a problem, see https://stackoverflow.com/questions/28632968/why-doesnt-rust-support-trait-object-upcasting – CoronA Dec 02 '19 at 05:12

1 Answers1

1

The question how to convert between those two types is still open.

For now I switched to https://crates.io/crates/failure crate for error handling in which Error type replaces Box<dyn Error + Sync + Send>, also making it easy to create custom and string (even formatted) errors.

peku33
  • 3,628
  • 3
  • 26
  • 44