Rust errors: Difference between revisions

From wikinotes
Line 40: Line 40:
</syntaxhighlight>
</syntaxhighlight>


You can treat this like Option using <code>match</code>:
{{ expand
| <code>match</code> the various cases
|
 
<syntaxhighlight lang="rust">
<syntaxhighlight lang="rust">
let result = match is_one(2) {
let result = match is_one(2) {
Line 48: Line 51:
println!("{}", result);
println!("{}", result);
</syntaxhighlight>
</syntaxhighlight>
}}
{{ expand
| Panic if not successful
|


But there are more concise ways of handling this
<syntaxhighlight lang="rust">
<syntaxhighlight lang="rust">
// panic if error, otherwise return value
// panic if error, otherwise return value
Line 59: Line 66:
     .expect("an error occurred!")  // <-- panic message
     .expect("an error occurred!")  // <-- panic message
</syntaxhighlight>
</syntaxhighlight>
}}
{{ expand
| Propagate the error if not successful
|
It's also fairly common that you want to delegate handling the error to the caller.<br>
There is also syntactic sugar for this.
The <code>?</code> operator returns with the <code>Err</code> if it errored.<br>
You'll only need to provide the <code>Ok()</code> value.
<syntaxhighlight lang="rust">
fn print_if_result_ok(r: Result<String, MyError>) -> Result<String, MyError> {
    let result = is_one(2)?  // return Err() if err
    println!("success value: {}", result);
    Ok("success")
}
</syntaxhighlight>
}}
</blockquote><!-- Result -->
</blockquote><!-- Result -->

Revision as of 18:27, 8 February 2023

Rust has two primary methods of handling errors.

  • panic!() halts/exits the program
  • Result types are for handle-able errors

panic

  • intended for halting application, not control flow
  • have backtraces
panic!("tried to X but couldn't Y")

// convert panic to result
// (not intended for native rust code)
let result = panic::catch_unwind(|| {
    panic!("oh no!");
});

Result

The result type is an enum, whose options Ok, Err have been merged into the global scope through prelude.

Given this Result producing code:

struct MyError {
    value: isize
}

fn is_one(i: isize) -> Result<String, MyError> {
    if i == 1 {
        Ok("success".to_string())

    } else {
        Err(MyError{value: i})
    }
}

match the various cases


let result = match is_one(2) {
    Ok(x) => format!("horay: {}", x),
    Err(_) => panic!("an error occurred")
};
println!("{}", result);

Panic if not successful


// panic if error, otherwise return value
let result = is_one(2)
    .unwrap()

// panic with message if error, otherwise return value
let result = is_one(2)
    .expect("an error occurred!")  // <-- panic message

Propagate the error if not successful

It's also fairly common that you want to delegate handling the error to the caller.
There is also syntactic sugar for this.

The ? operator returns with the Err if it errored.
You'll only need to provide the Ok() value.

fn print_if_result_ok(r: Result<String, MyError>) -> Result<String, MyError> {
    let result = is_one(2)?  // return Err() if err
    println!("success value: {}", result);
    Ok("success")
}