45

When it is known that some piece of code might throw an error, we make use of try/catch blocks to ignore such errors and proceed. This is done when the error is not that important but maybe we only want to log it:

try{
    int i = 1/0;
} catch( ArithmeticException e){
    System.out.println("Encountered an error but would proceed.");
} 
x = y;

Such a construct in Java would continue on to execute x = y;.

Can I make use of match to do this or any other construct?

I do see a try! macro, but perhaps it would return in case of an error with the return type of the method as Result.

I want to use such a construct in a UT to ensure it continues to run even after an error has occurred.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Rajeev Ranjan
  • 3,588
  • 6
  • 28
  • 52
  • *perhaps it would return* — I recommend reading [the documentation for functions, macros, and types that you find](https://doc.rust-lang.org/std/macro.try.html). A lot of time and effort has gone into them and they cover many basic questions. – Shepmaster Jul 02 '18 at 18:43
  • Thanks for pointing me to the resources @Shepmaster. But I had already gone through them. All the error handling variants appeared to me to be working only in case a Result type is being returned. But I was looking to handle some case very analogous to the try/catch mentioned above. My function returns a value and not a Result or Option type, but may panic which is what I wanted to ignore. – Rajeev Ranjan Jul 02 '18 at 18:57
  • 1
    You can use [catch_unwind](https://doc.rust-lang.org/std/panic/fn.catch_unwind.html) but it is not recommended. Docs "It is not recommended to use this function for a general try/catch mechanism. The Result type is more appropriate to use for functions that can fail on a regular basis." – user25064 Jul 02 '18 at 20:21
  • I think the reason why somebody downvoted your question is, that you should not "throw away" the error. Handle it properly (you may do this with `expect`) or return it, so the caller can handle the error itself. – hellow Jul 03 '18 at 06:15
  • 1
    Yes thanks @hellow for pointing it out. But its in a UT that I am willing to do this where anyways there are mocking and stuff to get around things. I might even go on to assert in the catch block but do not want to stop the progress of the UT. – Rajeev Ranjan Jul 03 '18 at 06:19

1 Answers1

74

Functions in Rust which can fail return a Result:

Result<T, E> is the type used for returning and propagating errors. It is an enum with the variants, Ok(T), representing success and containing a value, and Err(E), representing error and containing an error value.

I highly recommend reading the Error Handling section in the Rust Book:

Rust has a number of features for handling situations in which something goes wrong

If you want to ignore an error, you have different possibilities:

  • Don't use the Result:

      let _ = failing_function();
    

    The function will be called, but the result will be ignored. If you omit let _ = , you will get a warning. As of Rust 1.59, you can omit the let and just write _ = failing_function();.

  • Ignore the Err variant of Result using if let or match:

      if let Ok(ret) = failing_function() {
          // use the returned value
      }
    

    You may also convert the Result into Option with Result::ok:

      let opt = failing_function().ok();
    
  • Unwrap the error. This code panics if an error occurred though:

      let ret = failing_function().unwrap();
      // or
      let ret = failing_function().expect("A panic message to be displayed");
    

try!() unwraps a result and early returns the function, if an error occurred. However, you should use ? instead of try! as this is deprecated.


See also:

Tim Diekmann
  • 7,755
  • 11
  • 41
  • 69
  • 1
    Calling `Result::ok` just turns it into an `Option`. Then you basically have the same story as in `Result` – Tim Diekmann Jan 18 '20 at 17:12
  • 3
    Nope, because rustc _does_ complain about an unused Result but it _doesn't_ complain about an unused Option – phiresky Jan 19 '20 at 22:48
  • Not sure if there's a more idiomatic way to tell the compiler "I intentionally ignored that result" – phiresky Jan 19 '20 at 22:49
  • It's expressive to type `let _`. It gives a hint to the compiler, that you don't use the value and other readers (or youself at a later point) will see that, too. – Tim Diekmann Jan 20 '20 at 16:00
  • You can also use `unwrap_or` or `unwrap_or_default`. Example: `std::fs::remove_file(file).unwrap_or_default();` to delete a file, ignoring any errors. – harmic Aug 11 '20 at 22:49
  • How could you log an error (i.e., with `println!`) and proceed, as the OP originally asked? I've tried `.or_else` with no luck. – workerjoe Oct 13 '20 at 17:49
  • 1
    @workerjoe `.or_else` requires a return value. You may either use `if let Ok(...) = result { ... } else { println!(...) }` or a `match result { ... }` statement. – Tim Diekmann Oct 14 '20 at 11:06
  • 3
    As someone stumbling here with the same question, I believe `if let Ok(ret) = failing_function()` was the answer being searched for. I basically just didn't want to do `match failing_function() { Err(_) => {}, Ok(ret) => { ... }` – cdgraham Dec 18 '21 at 19:57
  • As of Rust 1.59, you can omit the `let` and just write `_ = failing_function();` in order to ignore the result of `failing_function()`. See https://twitter.com/davidtolnay/status/1564729670779604993, https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1590-2022-02-24 and https://github.com/rust-lang/rust/pull/79016 – Jeroen Wiert Pluimers Sep 03 '22 at 10:23
  • 1
    Thanks, @JeroenWiertPluimers, I added this to the answer. – Tim Diekmann Sep 04 '22 at 15:52