#result #ignore #productivity

no-std ignore-result

Adds a Result<_, _>.ignore() method to ignore the return value of a function call without panicking in case of error

2 unstable releases

0.2.0 Dec 24, 2018
0.1.0 Dec 24, 2018

#358 in No standard library

Download history 13281/week @ 2023-08-09 18405/week @ 2023-08-16 14789/week @ 2023-08-23 11407/week @ 2023-08-30 16173/week @ 2023-09-06 13471/week @ 2023-09-13 14885/week @ 2023-09-20 17020/week @ 2023-09-27 29677/week @ 2023-10-04 25519/week @ 2023-10-11 19300/week @ 2023-10-18 16026/week @ 2023-10-25 22660/week @ 2023-11-01 18676/week @ 2023-11-08 22745/week @ 2023-11-15 11233/week @ 2023-11-22

79,637 downloads per month
Used in 7 crates

MIT license

6KB

ignore-result for rust

Safely ignore errors in function return values when the result isn't critical

crates.io docs.rs

This crate adds a .ignore() function to Result instances that ignores both the Ok and Err variants of the result, silencing compiler warnings about unused errors without needing to resort to empty match blocks or panicking in case you call .unwrap() on what turns out to be an error.

Why do you need this?

There are cases involving correct error handling where it is desirable to call a method and "keep on keepin' on" even if it does not succeed, something often seen in FFI when interfacing with C APIs or on embedded systems.

As a concrete example, imagine that you have trapped an error and need to bubble it up to the caller, but first, you need to do your best to clean up some resource allocations, etc.

If you did this:

fn my_func() -> Result<(), E> {
    let foo = something_important()?;
    if foo.is_err() {
        // Oh no! We can't continue, need to report this error,
        // but first, try to clean up some state
        cleanup()?;
    }
    return foo;
}

The original error contained in foo would be lost if cleanup() failed (as the ? would trigger an early abort with the return value of cleanup() and not the original error Err(e) in foo).

And if you omitted the ? from cleanup()?, the compiler would warn you that there's a result that's not checked/used, because cleanup() can fail.

This is a "best effort" scenario where you hope that the function will succeed, there's nothing you can do if it doesn't, and there's a higher priority result (error) that should be persisted even if this step fails.

So you can either write this:

let foo = something_import();
if foo.is_err() {
    match cleanup() {
        _ => {}
    };

    return foo;
}

Or use this crate and write this instead:

use ignore_result::Ignore;

if foo.is_err() {
    cleanup.ignore();
    return foo;
}

and be on your merry way.

Why is this safe?

Calling foo().ignore() returns () regardless of whether foo() evaluated to Ok(_) or Err(_) -- meaning it guarantees that you are not (incorrectly) relying on an Ok(_) result.

The ignore function actually consumes the Result (being declared as fn ignore(self) -> ()) guaranteeing that after calling foo().ignore() there is no way to get at either the Ok or Err variants of the original result, which in turn means there's no way the caller can "presume it's Ok and use the return value" (which is the original motivation behind using monads rather than exceptions in rust), and it additionally makes your intent clear.

No runtime deps