4 ms·
That and the bizarre thinking that ".unwrap" is a perfectly ok thing to write in some cases (don't worry it will never make it to production!). No, ".unwrap" t
by p0nce 9y ago
That and the bizarre thinking that ".unwrap" is a perfectly ok thing to write in some cases (don't worry it will never make it to production!).
No, ".unwrap" turns input errors into bugs, and there is no production code where this is more desirable than an exception.
- burntsushi 9y agoOne of the hardest things about teaching error handling in Rust is that there is a lot of nuance. It's fun to say "unwrap is evil, don't use it," and more than that, it's not exactly wrong either. The nuanced version is that you shouldn't use unwrap for error handling, but: 1. If you're prototyping or writing a quick throwaway program, then unwrap will neither pick your pocket nor break your leg. 2. If you have an invariant that you either can't (or won't) move into the type system, then unwrap/expect/panic'ing can be appropriate precisely because if that unwrap gets tripped, then that will indicate a bug in your program that should be fixed. The more succinct advice that I like to use is this: "if end users of your Rust application see a panic, then you have a bug." But this is slightly harder advice to follow because it's a statement about the user experience.
- p0nce 9y ago> 2. If you have an invariant that you either can't (or won't) move into the type system, then unwrap/expect/panic'ing can be appropriate precisely because if that unwrap gets tripped, then that will indicate a bug in your program that should be fixed. Absolutely but using the same mechanism (unwrap/panic) for both types of errors - recoverable and recoverable - can creates confusion. panic'ing for wrong user input for example as can be seen in example code.
- kibwen 9y agopanics aren't for recoverable errors, in any circumstances. It is technically possible to "halt" the unwinding from a panic, but 1) that's intended for C interop, 2) the feature has been deliberately designed to make your life hell if you try to use it to emulate recoverable exceptions, and 3) Rust makes no guarantees that panics will unwind at all, it is entirely legal for a user to configure panics so that they all abort instead.
- p0nce 9y ago> panics aren't for recoverable errors, in any circumstances. And I understand that. Hence why unwrap everywhere is harmful.
- kibwen 9y agoEr, it was a response to this line of yours: > Absolutely but using the same mechanism (unwrap/panic) for both types of errors - recoverable and recoverable Nobody is using panics with the intent to recover, in the classic sense of "recoverable error".
- p0nce 9y agoSee above where one user is using .unwrap for parsing errors (input errors are recoverable).
- cyphar 9y agoNot in all cases. Most daemons will die if you give them an invalid configuration file (with a description of the syntax error).
- derefr 9y agoI think this discussion is muddying the meanings of "recoverable" between "recoverable as a class" and "recoverable in this instance." Parsing errors are recoverable as a class—you haven't irretrievably corrupted your process memory when you encounter one. Therefore, the parser itself should not panic(); it should just return an option type. Parsing errors may very well be unrecoverable in a particular instance. The code calling the parser has every right to decide to unwrap() the option type such that a panic() will happen if the parse failed. The code calling the parser is likely business-logic code of an application, and is privy to knowledge like "if there is no configuration supplied here, then later code that tries to consume the configuration will have to crash" and so can decide to early-exit with a user-comprehensible error ("you don't have a config file!") rather than letting the later code crash with some weird error about a config value being Nothing.
- twic 9y agoI don't get it. .unwrap() turns an undesirable situation into printing an error message and exiting with a nonzero status. There are plenty of situations where that is exactly what you want, and not a bug at all. For example, in my production Rust code, i deal with all errors in reading and parsing config files with .unwrap() or .expect(). If a program cannot read its config file at startup, it cannot correctly do its job, and so the only correct thing for it to do is to abort. Have i misunderstood what you were trying to say?
- p0nce 9y agoExceptions are well suited for parsing errors because they embed an error message.
- resf 9y agoPrints to where? stderr? Fine for a simple CLI tool, but people might want to do something more complicated when an "unrecoverable" exception occurs. Take for instance a web framework like Django that responds with a 500 error page with a stack trace when an exception occurs. There are interesting problems to be solved in the space of error handling, e.g. error handling in asynchronous code. But Rust is not even matching the state of the art achieved by Lisp and Python decades ago.
- pixel_fcker 9y ago...then don't use unwrap(). Instead check the error, do whatever handling you want and exit gracefully. unwrap()'s behaviour is essentially the same thing as an uncaught exception in Python, only you can actually check for where they occur in the code with a simple grep rather than hoping your test suite caught every possible failure case.