# If Rust does not have exceptions, then how do you handle errors in Rust?

> "Rust does not have exceptions".

This sounds very interesting, but what does it mean? Rust handles errors in a sophisticated manner, not like try-catch block type error handling. There are two approaches either panic for unrecoverable errors or use Result Enum for recoverable error. We could panic whenever we come across something messed up, a bug like divide by zero. Its not a crash, it means Rust walk back up the stack and clean up the data from each function it encounters. It’s more like a RuntimeException in Java or a std::logic\_error in C++. Lets focus on Result as it the topic of discussion. The use of [**Result**](https://doc.rust-lang.org/std/result) enum in error handling gives you a fresh perspective, potential best practices, and avoiding neglect. The use **Result** as a return type of functions forces you to think in a non-lazy approach about all the places/functions an error could occur and makes decisions like:

* Propagating errors to caller functions.
    
* Discarding errors or reacting to specific errors.
    

You end up thinking of error handling more in Rust as you need to decide if the function is fallible because the return type of function depends on it.

Let's first discuss the `Result<T,E>` enum here.

# `Result<T,E>`

Result is a built-in enum in the Rust standard library with two variants Ok(T) and Err(E).

*Ok(T): returns the success statement of type T.*

*Err(E): returns the error statement of type E.*

```rust
enum Result<T, E> {
   Ok(T),
   Err(E),
}
```

Result must be used as a return type for a function that can encounter error situations. Such functions can return an Ok value in case of success or an Err value in case of an error. Using Result as a function return type can be used to return various kinds of success and error codes to let the calling function decode the execution state of the called function.

```rust
fn abc(a:f64)->Result<f64,bool>{
        if a ==20.0{
            println!("Going good");
            Ok(a/2.0)
        }
            else if a<20.0 {
                Ok(a)
            }
        else {
            println!("this is error");
            Err(false)
        }
    }
match abc(10.0){
        Ok(T)=>{
            println!("What are you talking about? Here is no error!!")
        }
        Err(E)=>{
            println!("Finally caught a error!")
        }
    }
```

`match` looks like a try/catch block. As we received the Result enum, it requires some processing of `Result <T,E>` if we want to handle it instead of passing it to the caller. There are various methods that `Result <T,E>` provides to handle it. For example

```rust
pub fn unwrap_or(self, default: T) -> T
```

This returns the contained Ok value or a provided default.

```rust
let r = abc(40.0).unwrap_or(0.0);
println!("The value of r is {}",r);
```

# ? Operator

Rust has ? operator that helps to propagate the errors to the caller function. Any functions that return a Result, we can add ? like

```rust
let r = abc(20.0)?;
```

This unwraps the Result to get the value inside. In case of an error, it immediately returns from the enclosing functions, passing the error result up the call chain. This `?` looks pretty cool, isn't it?

# How to deal with multiple errors types

Let's say we are using `?` in multiple lines that have different error types in Result.

```rust
    fn abc(a:f64)->Result<f64,bool>{
        let x = x(a)?;
        let y = y(a)?;
        Ok(0.0)
    }
    fn x(a:f64)->Result<f64,String>{
        Err("Error in x".parse().unwrap())
    }
    fn y(a:f64)->Result<f64,bool>{
        Err(false)
    }
```

```rust
error[E0277]: `?` couldn't convert the error to `bool`
  --> src\main.rs:42:21
   |
41 |     fn abc(a:f64)->Result<f64,bool>{
   |                    ---------------- expected `bool` because of this
42 |         let x = x(a)?;
   |                     ^ the trait `From<String>` is not implemented for `bool`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = help: the following other types implement trait `FromResidual<R>`:
             <Result<T, F> as FromResidual<Result<Infallible, E>>>
             <Result<T, F> as FromResidual<Yeet<E>>>
   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, String>>` for `Result<f64, bool>`
```

The problem is two different types of errors types String and bool. We can deal with this using the Generic type.

```rust
type GenericError = Box<dyn std::error::Error + Send + Sync + 'static>;
type GenericResult<T> = Result<T, GenericError>;
```

# ! operator `Result<T, !>`

Often you need a function return type as Result to match trait signatures even though the function never fails. Rust provides the never type, written with the ! syntax. The never type represents a value that can never be generated.

# Useful Resources

%[https://read.amazon.com/kp/embed?asin=B0979PWD4Z&preview=newtab&linkCode=kpe&ref_=cm_sw_r_kb_dp_N4KZT47D9XZFFWW3JC10] 

%[https://www.youtube.com/watch?v=rAF8mLI0naQ&t=28] 

%[https://www.youtube.com/watch?v=wM6o70NAWUI&t=772s]
