5 ms·
Just to clarify since `unsafe` is a special term in Rust: `unwrap` still checks for None and panics, it doesn't blindly assume it's valid. That said, I think y
by Gankro 11y ago
Just to clarify since `unsafe` is a special term in Rust: `unwrap` still checks for None and panics, it doesn't blindly assume it's valid.
That said, I think you're too dismissive of "can never fail" assumptions. There's tons of places where something is optional in general, but based on various invariants you know it won't be. For instance, if you successfully acquire the first element in an array, you know you can get the last.
If you legitimately believe that Option is always Some, I don't understand what you think you would otherwise put there? Gonna have your function return an Err if an internal invariant is broken? Gonna have callers actually check for that?
- krisdol 11y ago>Gonna have your function return an Err if an internal invariant is broken? Absolutely you should return an error. Whether the caller wants to panic or handle it or print unicorns should be left up to the caller, not your function. Functions should not be expected to tear down the thread in case of an error. Nothing that panics should belong anywhere in exported code
- steveklabnik 11y agoThe idea is that Err is good if it's a recoverable error, but if it's not recoverable, you should panic!. Most errors are recoverable. panic! is an antipattern in a library. Or at least, provide both a panic-ing and a non-panic-ing variant.
- Gankro 11y agoWe specifically recommend against providing panicing and non-panicking. This causes horrible combinatoric explosions. There's very few exceptions to this (array indexing being the major exception). We do of course recommend non-panicking, but there's a few cases where the burden of checking for errors is too high (indexing, refcell). We're actually in the midst of arguing whether to violate this convention and do it for RefCell: https://github.com/rust-lang/rust/issues/27733 https://github.com/rust-lang/rust/issues/27733
- steveklabnik 11y agoYeah, I was thinking of things like array access. The stuff that's on the wrong end of the cost/benefit ratio.
- fauigerzigerk 11y agoThe problem is that a function cannot know whether or not the caller can recover from a particular error, so there's no point in making that distinction in the first place.
- steveklabnik 11y agoIt's part of your API design, if they are recoverable or not. You should lean towards recoverable: if the caller can't recover, they can always do something with it. But some kinds of problems are non-recoverable.
- fauigerzigerk 11y agoCan you name one such unconditionally unrecoverable problem?
- steveklabnik 11y agoSay you have a library which has some kind of internal state, and the consistency of said internal state is important for memory safety, as other operations rely on it. Using assert! to verify that your state is consistent is useful, in case you have a bug. But since it's all internal, it's not something that the caller can really recover from, either. It's not their fault, it's yours.
- krisdol 11y agoWell here's my issue with this explanation that I've heard a lot: the caller may or may not be able to recover from it, but the caller may still be doing something with the error. Maybe the caller doesn't want to expose the error to its caller, or maybe the caller wants to build a new message to explain the cause of your error. But to panic! takes away a lot of options for the caller. Worst of all, it leads to untestable code, because the calling test case can't properly check the error against some known result.
- 11y ago
- Gankro 11y agoThis seems a bit too unpragmatic. Would you also require the user to explicitly handle: * Index out of bounds on every array op * Integer overflow on every arithmetic op * OOM on every allocating op Maybe if you're writing an ironclad RTOS for a critical system without any good redundancy? Otherwise these are such pervasive operations that most have accepted that they're not worth handling everywhere they happen. Requiring that really dilutes the value/meaning of errors. Given this signature: fn do_thing() -> Result<T, E> There's a clear signal that there's legitimate error conditions that you probably want to think about today. If every function that accessed arrays, worked with integers, or allocated memory returned a Result, it would border on meaningless. It would be like if there was no Throwable/Exception distinction in Java. Everything would `throw Exception`, eliminating the value of even noting that something can fail. I think the only way such a system could be tolerable is if the language in question had really good dependent type support (but that wouldn't handle the OOM issue -- which you can't even reliably handle on some systems). Unwinding/crashing is valuable in a truly robust system, because it needs to handle crashes anyway. Might as well punt obscure problems to that level of the reliability system. (This is basically the basis of Erlang's task system, AFAIK)
- valarauca1 11y ago>Requiring that really dilutes the value/meaning of errors. No. You have already diluted the meaning of errors, and you want them elevated to _your_ standard. >Index out of bounds on every array op These are removed if you build a rust program with --release. >Integer overflow on every arithmetic op Add the Wrapping class if you expect overflow. Overflow _shouldnt_ normally happen on an Integer operation. It is a hardware error when it happens, and can cause massive pain-in-ass bugs when it happens unexpectedly. I'd rather get errors when it does happen, rather then find out 6 months into a production run. >OOM on every allocating op C does this also.
- Gankro 11y agoWhat have I diluted the meaning of errors to? Rust doesn't remove bounds checks in --release. It's wrapping that gets turned on in release. I'm not sure why you're distinguishing overflow as truly exceptional, as opposed to any other "this should never happen" error? Also I don't think many C libraries that allocate expose that as a failure condition (I've certainly seen some which don't even check!)