Macro return_multiple_errors

Source
macro_rules! return_multiple_errors {
    (
        let mut $errors:ident: Vec<$E:ty> = $initial_errors:expr;
        $(
           let $var:ident = $expr:expr;
        )+
        if_there_are_errors {
           return $return_val:expr;
        }
    ) => { ... };
}
Expand description

Given a bunch of Results, return a non-empty Vec of errors or unwrap all Results and proceed.

§Usage

The first statement should define a mutable Vec of errors, usually empty.

The statements that follow should define Result variables with the same (or convertible) error type.

Finally, the last statement should define a diverging branch with the following shape:

if_there_are_errors {
  return /* the vec of errors or some other expression */;
}

§Examples

fn a_b_c() -> Result<(A, B, C), Vec<HighLevelErr>> {
    return_multiple_errors!(
        // Annotate the "common" error type for the container of errors.
        let mut errors: Vec<HighLevelErr> = vec![];
        // Get some `Result`s.
        let a = action_a();
        let b = action_b();
        let c = action_c();
        // If there are any errors, they are implicitly converted and collected.
        if_there_are_errors {
            return Err(errors);
        }
    );
    // And here we can proceed on the happy path, with already-unwrapped `Ok` values.
    // `a`, `b`, and `c` are no longer `Result`s. They have been shadowed.
    Ok((a, b, c))
}

§Some nice details

  • Ok types don’t have to be the same
  • Errors don’t have to be Clone