Live data from Hacker News

Using unwrap() in Rust is Okay (2022)

burntsushi.net

41–50 of 54 posts

Re: Using unwrap() in Rust is Okay (2022)

#41

Just don’t put unwrap in library code, please. Not if it can possibly happen, bearing in mind that you can make mistakes. I like my background threads to be infallible. If they panic, then chances are nothing will notice and the rest of the program will solely seize up. I might have agreed with more of this article if panics actually crashed the program, but in multithreaded Rust that’s rarely the case.

I believe that your argument is implied in the article. Errors that are expected at runtime must be handled (preferably in the application code), instead of unwrapping it. If the thread does panic due to an unwrap (even without crashing the main thread), it's a logical error in the library that must be resolved before the public/production release.

There are cases where unwrap may be necessary even within a library. Burntsushi's own regex crate has an example of this. You get a Result when you construct a regex - which is reasonable if the regex is parsed at runtime. But I don't see any reason to not use unwrap, if the expression is a static string within the library source.

Re: Using unwrap() in Rust is Okay (2022)

#42
post #27
post #7

I only use unwrap in tests

I use expect() so that I can grep for instances of "unwrap()" after the prototyping phase without getting tests.

You can add

    [lints.clippy]
    unwrap_used = "deny"
to Cargo.toml if you want to avoid unwrap and then explicitly opt-in with #[allow(clippy::unwrap_used)]

Re: Using unwrap() in Rust is Okay (2022)

#43
unwrap() is fine for experimental and WIP code. But it's a code smell for production. I usually do a git grep for unwrap and go one of two ways:

1. convert to an expect() - even if a panic is fine, you at least owe the future reader an explanation.

2. Use "proper" result handling, usually let Some, .ok_or, or a match.

Unwrap is a nice ergonomic cheat code to get the program compiled and leave a little TODO for yourself. You just need the discipline to circle back and clean them up, just like any debugging tool.

Re: Using unwrap() in Rust is Okay (2022)

#44
post #5
post #3

> That section briefly described that, broadly speaking, using unwrap() is okay if it’s in test/example code or when panicking indicates a bug. I've come to the conclusion that even in tests unwraps look ugly. Especially in doc tests which serve as examples the code is better off using regular "?" that one would see in other parts of code. (that is: don't treat test code as a "worse" kind of code) In Signstar we're u…

I always felt unwrap is preferable for diagnosing issues, which makes it useful in tests. A failed unwrap will point you directly to the line of code which panics, which is much simpler than trying to trace an issue through many layers of Results. If you use `assert` in tests, I don't understand why you wouldn't also prefer unwrap in this context. I think it's also perfectly reasonable to use in a context like binary…

> I always felt unwrap is preferable for diagnosing issues, which makes it useful in tests. A failed unwrap will point you directly to the line of code which panics, which is much simpler than trying to trace an issue through many layers of Results.

Take a closer look at testresult since it also points directly at the exact line of failure (due to panics being used under hood) but looks nicer.

Re: Using unwrap() in Rust is Okay (2022)

#45
post #21

Earlier quoted context omitted.

I'm not as familiar with the Rust ecosystem, but I know it is used all the time in Go. For example, the standard http server library wraps user provided endpoint handler functions with panic handlers.

Is that used for application-level errors though? Rust web servers do that too, but it is used a fallback to avoid bringing down the whole server due to an unexpected crash. It is not a mechanism you would use intentionally.

encoding/json uses uses exception handlers for control flow.

Re: Using unwrap() in Rust is Okay (2022)

#46
post #16

Earlier quoted context omitted.

> which removes any temptation to use them for user errors. It doesn't look to be too much of a temptation to use panics as regular errors in Rust though, so I don't think it gains you much. And it makes it more complicated when you want to catch panics for legitimate reasons (like when you want to show an error box to the user, instead of silently crashing, or when you want to send the crash log for later analysis).…

> It doesn't look to be too much of a temptation to use panics as regular errors in Rust though Maybe not, but it was enough for the author to dedicate at least one whole section of the article to reasoning about this. > like when you want to show an error box to the user, instead of silently crashing, or when you want to send the crash log for later analysis As I mentioned, panics can be handled but not recovered .…

> As I mentioned, panics can be handled but not recovered. You can use the panic handler to do these things just fine. Just not recover.

What does this difference mean? If you can run arbitrary function in your panic handler, what prevents someone from continuing the program?

Re: Using unwrap() in Rust is Okay (2022)

#47
post #8

The article pretty much says this as well, but a concise way I saw Andrew Kelley put it recently in the context of Zig (but it seems to apply well for any language that has errors-as-values + panics) is: "Assertions for programmer mistakes; errors for user mistakes."[0] One interesting difference between Zig and other languages with similar error stories (Rust, Go) is that panicking can be handled but not recovered .…

> panicking can be handled but not recovered. Panicking is always fatal in Zig.

What does it mean to "handle" but not "recover" a panic?

Re: Using unwrap() in Rust is Okay (2022)

#48
post #8

The article pretty much says this as well, but a concise way I saw Andrew Kelley put it recently in the context of Zig (but it seems to apply well for any language that has errors-as-values + panics) is: "Assertions for programmer mistakes; errors for user mistakes."[0] One interesting difference between Zig and other languages with similar error stories (Rust, Go) is that panicking can be handled but not recovered .…

> panicking can be handled but not recovered. Panicking is always fatal in Zig. What does it mean to "handle" but not "recover" a panic?

Dumping the log somewhere, telling the user that the program is exiting, things like that.

Re: Using unwrap() in Rust is Okay (2022)

#49
post #21

Earlier quoted context omitted.

I'm not as familiar with the Rust ecosystem, but I know it is used all the time in Go. For example, the standard http server library wraps user provided endpoint handler functions with panic handlers.

I suppose it's a matter of perspective but I don't see returning a 500 as "Recovering from the error". The user's request has still failed. It just hasn't taken down the server. IMO this is still fine.

It is quite literally using the "recover" function in go, so I think it's accurate to call it "recovering".

> this is fine

I didn't mention the merit, just that it is exception style control flow.

Re: Using unwrap() in Rust is Okay (2022)

#50
post #21

Earlier quoted context omitted.

I'm not as familiar with the Rust ecosystem, but I know it is used all the time in Go. For example, the standard http server library wraps user provided endpoint handler functions with panic handlers.

Is that used for application-level errors though? Rust web servers do that too, but it is used a fallback to avoid bringing down the whole server due to an unexpected crash. It is not a mechanism you would use intentionally.

Probably not. I have never used panic / recover in application code at least.
Post reply on HN