3

I currently have the below code to handle the case where I want to handle an error without propagation or continue the function. The use case for this is a web server controller, where I would prefer to manual handle possible errors - which is why the return type is HttpResponse.

I want to know if there is a way to do this without this unwrap call as in my understanding the compiler should know there is a way to unwrap to a value at this point with no risk of panic.

    // ...
    
    let result: Result<u8, Error> = func_that_could_error();
    if result.is_err() {
        return HttpResponse::InternalServerError();
    }
    let value: u8 = result.unwrap();
    
    // ...
Acorn
  • 24,970
  • 5
  • 40
  • 69
JamesGill
  • 183
  • 11
  • 1
    `let value = result.map_err (|_| HttpResponse::InternalServerError())?;` – Jmb Mar 15 '22 at 13:33
  • or `let value = match result { Err(_) => return HttpResponse::InternalServerError()), Ok (v) => value, };` – Jmb Mar 15 '22 at 13:35

1 Answers1

5

If you can, use ?:

let value = func_that_could_error()?;

Optionally mapping it to your error as @Jmb suggests:

let value = func_that_could_error()
    .map_err(|_| HttpResponse::InternalServerError())?;

Otherwise, use let else:

let Ok(value) = func_that_could_error() else {
    return HttpResponse::InternalServerError();
};

Or, for Rust < 1.65, match:

let value = match func_that_could_error() {
    Err(_) => return HttpResponse::InternalServerError(),
    Ok(v) => v,
};
Acorn
  • 24,970
  • 5
  • 40
  • 69
  • There's an extra `if` in your `let-else` example. – Jmb Mar 15 '22 at 13:39
  • 1
    Also while `let-else` is still unstable, [guard](https://crates.io/crates/guard) implements it via a macro (with a few limitations) and is quite reliable, and has worked fine (on stable) for years. Basically wrap the entire thing (except the trailing `;`) in a `guard!()` and you're done. – Masklinn Mar 15 '22 at 14:08
  • Note: you can only use `?` if your function's return type is either `Result` or `Option`. – aedm Mar 15 '22 at 14:28
  • 1
    Thanks for the options. The `let-else` is ideal but stuck with stable at the moment. Will be following the RFC for sure. – JamesGill Mar 15 '22 at 23:47
  • @JamesGill Youre welcome. I added `match` alternative. – Acorn Mar 19 '22 at 16:59
  • Use `ok_or()` for `Option` instead of `Return` ;-) – jaques-sam Feb 16 '23 at 10:55