Should I avoid a U-turn in a production application?

Easy crash on startup with unwrap :

 fn main() { c().unwrap(); } fn c() -> Option<i64> { None } 

Result:

  Compiling playground v0.0.1 (file:///playground) Running `target/debug/playground` thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', ../src/libcore/option.rs:325 note: Run with `RUST_BACKTRACE=1` for a backtrace. error: Process didn't exit successfully: `target/debug/playground` (exit code: 101) 

Is unwrap just for quick tests and proof of concept?

I canโ€™t say: โ€œMy program will not crash here, so I can use unwrap โ€ if I really want to avoid panic! at runtime, and I think to avoid panic! - this is what we want in a production application.

In other words, can I say that my program is reliable if I use unwrap ? Or should I avoid unwrap , even if the matter seems simple?

I read this answer:

Best used when you are sure that you have no mistake.

But I donโ€™t think I can be โ€œsure.โ€

I do not think this is a matter of opinion, but a question about the Rust core and programming.

+8
error-handling rust
source share
4 answers

While all--topic error handling is very complex and often opinion based, this question can actually be answered here because Rust has a rather narrow philosophy. I.e:

  • panic! for programming errors ("errors")
  • correct propagation and error handling with Result<T, E> and Option<T> for expected and recoverable errors

You might think of unwrap() as a conversion between these two types of errors (it converts the error being restored to panic!() ). When you write unwrap() in your program, you say:

At this point, the value None / Err(_) is a programming error, and the program cannot restore it.


For example, let's say that you are working with a HashMap and want to insert a value that you might want to change later:

 age_map.insert("peter", 21); // ... if /* some condition */ { *age_map.get_mut("peter").unwrap() += 1; } 

Here we use unwrap() , because we can be sure that the key stores the value. It would be a programming error if it were not so and even more important: it is not restored. What would you do when at this moment there is no value with the key "peter" ? Try pasting it again ...?

But, as you know, there is a beautiful entry API for maps in the Rust standard library. Using this API, you can avoid all these unwrap() s. And this applies to almost all situations: you can very often restructure your code to avoid unwrap() ! Only in very few situations around this is not. But then it is OK to use it if you want to signal: at the moment this will be a programming error.


Recently, a rather popular blog post appeared on the topic "error handling", whose conclusion is similar to the philosophy of Rust. This is quite a long time, but it is worth reading: "Error Model . " Here is my attempt to summarize an article on this subject:

  • deliberately distinguish between programming errors and error recovery
  • use the fail fast method to program errors.

In conclusion : use unwrap() when you are sure that the error you are recovering is not actually being restored at this point. Bonus points for explaining why? in the comment above the affected line ;-)

+17
source share

In other words, can I say that my program is reliable if I use U-Turn? Or should I avoid a reversal, even if the matter seems simple?

I think using unwrap reasonable - this is what you should learn to handle, it cannot just be avoided.

My rhetorical barrage question will be:

  • Can I say that my program is reliable if I use indexing on vectors, arrays or slices?
  • Can I say that my program is reliable if I use integer division?
  • Can I say that my program is reliable if I add numbers?

(1) itโ€™s like a reversal, indexing panic, if you break the contract and try to index beyond. This will be a bug in the program, but it does not attract attention, like calling unwrap .

(2) is like a reversal, integer divisions of a panic if the divisor is zero.

(3) differs from a reversal, the addition does not check for overflow in the release builds, so it can silently lead to errors and logical errors.

Of course, there are strategies for processing all this data, without leaving panic cases in the code, but many programs simply use, for example, checking boundaries as they are.

+4
source share

There are two questions here:

  • - use panic! acceptable in production
  • - Use unwrap acceptable in production

panic! is a tool that Rust uses to signal irregular situations / broken assumptions. It can be used to crash a program that cannot continue in the face of this error (for example, the situation with OOM) or to work with the compiler, knowing that it cannot be executed (at the moment).

unwrap is a convenience that is best avoided in production. The problem with unwrap is that it does not indicate which assumption has been violated; instead, it is better to use expect("") , which is functionally equivalent, but will also give an idea of โ€‹โ€‹what went wrong (without opening the source code) .

+2
source share

unwrap() not necessarily dangerous. As with unreachable!() , There are times when you can be sure that some condition will not be triggered.

The returned Option or Result functions are sometimes just suitable for a wider range of conditions, but because of how your program is structured, these cases can never happen.

For example: when you create an iterator from Vec tor, which you yourself create, you know its exact length and you can be sure how long to call next() on it returns Some<T> (and you can safely unwrap() it).

+1
source share

All Articles