Errors in Rust are nothing but logics or syntaxes which are illegal and causes an interruption in the normal working of the program.
There are two different types of errors, which are:
This has to be noted that, in other programming languages there are methods where we can use exceptions for handling errors. But in Rust, there are no such facility. Rust handles errors in a different way.
Result<T,E>
.panic!()
.
This kind of errors can be handled by the user, which means that the user can not recover from the error. When this kind of errors occurs, then the macro panic! is automatically involked by the Rust compiler and the program execution stops.
It may be noted that the macro can also be called from the user's side also.
fn main() {
panic!("Hello");
}
In the above program output, we are have intentionally invoked the macro panic()! to see how the program execution stops.
Program Output :
thread 'main' panicked at 'Hello', rust-error-panic.rs:2:4
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
In the next example, we shall seen how an error will automatically call the macro panic!()
. Here, we shall refer to an array index which is not present.
Program which abort the program(macro panic!()
is called in the background automatically)
fn main() {
let a = [1,2,3];
a[4];
}
In the above program we have declared an array whose size of 3. This array has index starting from 0 to 2. Now when we tried to print the element from an index 4, which is not present, we are creating an error for the program flow and it is non-recoverable. Therefore, the macro panic()! is called to abort the program.
Program Output :
error: index out of bounds: the len is 3 but the index is 4
--> rust-error-panic-calling.rs:3:4
|
3 | a[4];
| ^^^^
|
= note: #[deny(const_err)] on by default
error: aborting due to previous error
This can be explained by considering the example below, where we use the macro panic!(), if the program flow is transferred in an else
block of an if-else
program.
fn main() {
let number = 123;
if number == 123 {
println!("Number is same");
}
else {
panic!("Number is not same. Panic is invoked");
}
}
Program Output :
thread 'main' panicked at 'Number is not same. Panic is invoked', rust-error-panic-invoke.rs:7:9
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Recoverable Errors are those errors which can be handled by the compiler. When this kind of error occurs, then the enum - Result <T,E>
.
The enum Result <T, E> has two variants- T and E which are generic parameters. If in case, there is no erros then the variant T will be returned. Otherwise, the variant E will be returned.
Syntax :
enum Result<T,E> {
OK(T),
Err(E)
}
Program to search for a file
use std::fs::File;
fn main() {
let file = File::open("my_pic01.jpg");
match file {
Ok(file) => {
println!("file found {:?}", file);
},
Err(err) => {
println!("file not found {:?}", err);
}
}
println!("Hello! The program is still in flow.The error was handled properly");
}
In the above program we are willing to search for a file, which is not present inside the directory. And thus it is an error. Now the way to handle the error is to execute the Err
part, and so that the error is handled and then the program flows normally.
Program Output :
file not found
Os { code: 2, kind: NotFound, message: "The system cannot find the file specified." }
Hello! The program is still in flow.The error was handled properly
The function unwrap()
returns a panic if an operation fails along with printing the default error message. Otherwise, it will return an the actual result.
A program to check whether a number is even
unwrap() & expect()
unwrap()
The function
unwrap()
returns a panic if an operation fails along with printing the default error message. Otherwise, it will return an the actual result.
A program to check whether a number is evenfn main() { let result = check(8).unwrap(); println!("Our check returned a {} result", result); } fn check(no: i32) - > Result < bool, bool > { if no % 2 == 0 { return Ok(true); } else { return Err(false); } }
In the above program, we have concatenated the function
unwrap()
, with the function in operationcheck()
. The function check(), returns an enum which has two default variants- OK and Err. When the check functions returns a true, that is when the number is even, then theOK
part is executed and the keywordtrue
is returned.
On the otherhand, when thecheck()
function returns a false, then the macrounwrap()
is automatically invoked to print the error message.
Program Output :
Case1 : When the number is even (TRUE case)
Program Output :
Case 1: When the number is not even (FALSE case)thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: false', src\libcore\result.rs:997:5 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
expect()
Using the function
expect()
, we can generate custom message for an error. This is helpful, because the compiler generated messages are somewhat very technical and may not be always understood by everyone.
A program to check whether an integer is even (FALSE Case)fn main() { let result = check(81).expect("Error, this is a custom error message"); println!("Our check returned a {} result", result); println!("Hello, there was no error. Let us continue.."); } fn check(no: i32) -> Result < bool, bool > { if no % 2 == 0 { return Ok(true); } else { return Err(false); } }
Program Out (When the function
check()
returns a false)C:\Users\HP\checker\src>rust-error-expect thread 'main' panicked at 'Error, this is a custom error message: false', src\libcore\result.rs:997:5 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Recommended Readings
Comment / Suggestion SectionPoint our Mistakes and Post Your Suggestions