Failing to port from error-chain to std error handling

I’ve defined an errors.rs module (shown at the end).
When I use it to raise a custom error when I wait for a child process, I get a compiler error. Here’s some of the relevant code:

fn run_test(test: &Test) -> XResult<i32> {
/// elided lines
    let output = child.wait_with_output().or_else(|err| {
        xerror(&format!(
            "Failed to run \"{}\": {}",
            test.app.display(),
            err
        ))
    })?;
/// elided lines

And here’s the error:

error[E0308]: mismatched types
   --> src/plan/process.rs:305:9
    |
305 | /         xerror(&format!(
306 | |             "Failed to run \"{}\": {}",
307 | |             test.app.display(),
308 | |             err
309 | |         ))
    | |__________^ expected struct `std::process::Output`, found ()
    |
    = note: expected type `std::result::Result<std::process::Output, _>`
               found type `std::result::Result<(), errors::XError>`

My xerror function is trying to replace the error-chain bail! macro.

Here’s my errors.rs:

use std::error::Error;
use std::fmt;
use std::io;
use std::num;

pub type XResult<T> = Result<T, XError>;

pub fn xerror<T>(message: &str) -> XResult<()> {
    Err(XError::new(&message))
}

#[derive(Debug)]
pub enum XError {
    Image(image::ImageError),
    Io(::std::io::Error),
    Json(json::Error),
    Log(log::SetLoggerError),
    ParseFloat(::std::num::ParseFloatError),
    ParseInt(::std::num::ParseIntError),
    Rayon(rayon::ThreadPoolBuildError),
    Retest(String),
}

impl Error for XError {}

impl XError {
    fn new(message: &str) -> XError {
        XError::Retest(message.to_string())
    }
}

impl fmt::Display for XError {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            XError::Image(ref err) => write!(out, "Image error: {}", err),
            XError::Io(ref err) => write!(out, "File error: {}", err),
            XError::Json(ref err) => write!(out, "JSON error: {}", err),
            XError::Log(ref err) => {
                write!(out, "Failed to set logger: {}", err)
            }
            XError::ParseFloat(ref err) => {
                write!(out, "Failed to read decimal number: {}", err)
            }
            XError::ParseInt(ref err) => {
                write!(out, "Failed to read whole number: {}", err)
            }
            XError::Rayon(ref err) => {
                write!(out, "Failed to create thread pool: {}", err)
            }
            XError::Retest(ref err) => write!(out, "{}", err),
        }
    }
}

impl From<image::ImageError> for XError {
    fn from(err: image::ImageError) -> XError {
        XError::Image(err)
    }
}

impl From<io::Error> for XError {
    fn from(err: io::Error) -> XError {
        XError::Io(err)
    }
}

impl From<json::Error> for XError {
    fn from(err: json::Error) -> XError {
        XError::Json(err)
    }
}

impl From<log::SetLoggerError> for XError {
    fn from(err: log::SetLoggerError) -> XError {
        XError::Log(err)
    }
}

impl From<num::ParseFloatError> for XError {
    fn from(err: num::ParseFloatError) -> XError {
        XError::ParseFloat(err)
    }
}

impl From<num::ParseIntError> for XError {
    fn from(err: num::ParseIntError) -> XError {
        XError::ParseInt(err)
    }
}

impl From<rayon::ThreadPoolBuildError> for XError {
    fn from(err: rayon::ThreadPoolBuildError) -> XError {
        XError::Rayon(err)
    }
}

Isn’t

pub fn xerror<T>(message: &str) -> XResult<()>

supposed to read

pub fn xerror<T>(message: &str) -> XResult<T>

?

2 Likes

Yes; thank you!

1 Like