IMHO, unwrap() , expect() and company, has infected the Rust language so deeply that one wonders when (and not "if") will a library send a panic and crash the whole program.
How could be erased those panic! methods that are used in most of Rust's libraries is something that may be is beyond the possible? beside is promoted from all the Rust's tutorials and reference code.
So much correctness in the Rust language just for to promote to all the community to crash the program from libraries without handling the error is something I can not understand.
I hope this philosophy do not reach the Linux kernel.
> How could be erased those panic! methods that are used in most of Rust's libraries is something that may be is beyond the possible?
It's arguably quite possible, though not as straightforwards as one may hope. For example, there's no_panic, which results in a linker error if the compiler cannot prove a function cannot panic [0], albeit with some caveats.
> So much correctness in the Rust language just for to promote to all the community to crash the program from libraries without handling the error is something I can not understand.
Is there that much "promoting" of unchecked unwrap()/expect()/etc. going on? How do you distinguish that from "genuine" cases of violations of the programmer's assumptions?
I ask because Result/? along with libraries like thiserror/anyhow/etc. are right there and arguably easier/more concise, so unwarranted unwrap()/etc. would seem "harder" to write/justify than the alternative. The main exception I can think of are more one-off cases where the author is intentionally sacrificing robust error handling for the sake of speed/convenience, but that's a more language-agnostic thing that pretty much "doesn't count" by definition.
> I hope this philosophy do not reach the Linux kernel.
IIRC this is being worked on, especially given Linus's position on panics in the kernel.
> Is there that much "promoting" of unchecked unwrap()/expect()/etc. going on? How do you distinguish that from "genuine" cases of violations of the programmer's assumptions?
More like promoted indirectly, I think by being used widely on reference code and tutorials the programmers absorbs as a familiar and quick to write method without planning much. And at same time by not being actively promoted that such methods should not be used within a library runtime or similar at least, because many people do not see it as wrong, what convert it in philosophy I guess.
When the dependency chain of library loading is fired, almost always I checked some unwrap ends within the program's runtime, so distinguishing whether those are genuine cases of violations (IMHO they can't be genuine if a lib can panic the program), or if it was just a unfinished prototyping part or etc, I think is not exactly important as individual until it reach terms of generalized behavior along the language libraries, and even seen in some programs of the community.
> IIRC this is being worked on, especially given Linus's position on panics in the kernel.
> More like promoted indirectly, I think by being used widely on reference code and tutorials the programmers absorbs as a familiar and quick to write method without planning much.
For references/documentation/tutorials I think the use of unwrap() and friends is a tradeoff. It (arguably) allows for more focused/self-contained examples that better showcase a particular aspect, though with the risk that a reader uses those examples as-is without taking other factors into consideration. There's also the fact that documentation examples can be used as tests, in which case use of unwrap() in docs/examples/etc. is arguably a good thing.
> And at same time by not being actively promoted that such methods should not be used within a library runtime or similar at least, because many people do not see it as wrong, what convert it in philosophy I guess.
I think it might depend on where you're looking. For example, the Rust book has a section titled "To panic! or Not to panic!" [0] which outlines some things to consider when deciding whether to panic/call unwrap()/etc. Not sure if that counts as active promotion, but the fact it's in official docs should count for something at least.
> IMHO they can't be genuine if a lib can panic the program
I feel this is a rather strong position to take. Given how panics are intended to be used (handling unexpected state/precondition violations/etc.), it seems it seems akin to saying "just don't write bugs", which would certainly be nice but isn't really realistic for the vast majority of development. I suppose one could hypothetically bubble up every possible error but that comes with its own maintainability/readability/etc. costs.
In addition, that stance seems similar to stating that there's no "genuine" assertion failures or similar in libraries, which seems... bold? What would the alternative be?
> or if it was just a unfinished prototyping part or etc
At least in Rust there's todo!() and unimplemented!() which more directly convey meaning.
`unwrap()` contains an assertion. Just like `slice[i]` or even `Box::new(whatever)`. The way to avoid these in C is to commit UB instead of panicking. I've seen arguments that seem understandable for why this is maybe appropriate in the Linux kernel ("I'd rather continue executing with garbage than shut down the user's system"), but I don't think it applies much beyond that. And to be clear, I'm not saying I agree with that either.
> Given how panics are intended to be used (handling unexpected state/precondition violations/etc.), it seems it seems akin to saying "just don't write bugs"
It is more about always making the error reach the function that called the method/library (lost if one of the own dependencies of this library rise the panic [UB included] crashing the program), what allows the programmer to take the decision (and not to a deep dependency^5 ) about if to continue running the program, by taking alternative route, or not.
The thing is that that kind of design isn't an unambiguous good; there are tradeoffs involved. Writing code in that manner means every single possibly-falliable operation must return an Option/Result/etc, said result checked, and the error bubbled up or the result used as appropriate. This can be quite noisy, especially before Rust 1.13.0, where users had to make do with the try!() macro instead of the ? operator. That can have negative impacts on readability/maintainability/clarity/etc. which may arguably outweigh benefits from allowing callers to handle errors, especially if callers usually don't.
This is also "viral", in that the use of any possibly-falliable operation in the implementation would require the corresponding public API to return a Result/Option/etc., even if the intent is that a correct implementation could never fail. This makes the public API clunkier, especially if/when all possible bugs are shaken out or their absence proved one way or another.
I'm guessing this kind of tradeoff is why (most?) indexing operations in Rust return the value instead of an Option/Result/etc - perhaps the team judged that most of the time users have some other way of guaranteeing success (e.g., checking indices) so panicking on failure better fits/streamlines the needs/use cases of most users rather than forcing them to constantly deal with an Option/Result/etc., especially since get()/etc. exists for those users who do want an infalliable option.
Presumably the author(s) of the library/libraries you're using made a similar judgement - while it's possible to write code in the way you desire, perhaps it just wasn't worth the bother for them and/or most of their users.
In other words, "every bug should be an error, and every failure should be an error." Except in order to make every bug be an error, you have to, well, know about every bug. And now all of your implementation details leak out into your public API errors.
Not exactly. It is more like if a library is gonna crash the program (the deep dependencies used in that library triggered a panic on its own), just to let the programmer know it before happens; thus allowing the programmer to try alternatives for to avoid it, and if it's inexorable after those tries, for procedures for a controlled shutdown with proper protocols, actions, and so on.
I mean, as the crash is not exposed in the public API, given the things, I think it might not matter if this signal is exposed or not.
By the public API then, may be a language generalized Err(panicked) through Result, nothing more as it is about the request cannot be accomplished at all (target/debug would tell), or may be someone thought on simpler tip through compiler or other thing. I humbly do not know what approach would be simpler, efficient or less intrusive, I would embrace anything to avoid sudden crash.
The juxtaposition between this comment where you seem to have absolutely no idea what you're talking about, and the certainty with which your initial comment was expressed is really quite something.
My initial comment was: So much correctness in the Rust language just for to promote to all the community to crash the program from libraries without handling the error is something I can not understand.
Empathy tone changed in such last message which you are ridiculing, it is the point within all my comments, the behavior of a --release.
I should not have had dialogue as the things are not going to change. What I take with me is to think on alternative for panic/unwrap is something only come from ignorance, the best is to crash a program without let the programmer nor the final user to blink; to think in a different behavior in Rust is ridiculous. This is what is really quite something.
> I hope this philosophy do not reach the Linux kernel.
Well, I hope it does. Albeit it almost certainly will not, because Linus is opposed to it. But ever since I read Joe Duffy's blog posts on the Midori research project at MS, I have been convinced that using panics leads to increased reliability, not decreased. From his blog[1]:
"Given that bugs are inherently not recoverable, we made no attempt to try. All bugs detected at runtime caused something called abandonment, which was Midori’s term for something otherwise known as “fail-fast”."
And:
"Abandonment, and the degree to which we used it, was in my opinion our biggest and most successful bet with the Error Model. We found bugs early and often, where they are easiest to diagnose and fix."
I think that the Midori team's work shows that a practice of "there's a bug, stop everything" leads to more reliable software. Sure, there's an initial period of pain where you're fixing a ton of bugs as they cause the software to panic. But you reap the rewards of that effort. I don't think Linux will ever move towards a model like this, but I think it would be beneficial in the end if they did.
Eh? There isn't a single unwrap/expect in the examples at the top level crate documentation. There should be very few overall. But there are hundreds of executable doctests, so there are certainly some unwraps.
It's done in bad faith. Some are vehemently against Rust because of the "culture" around criticizing other languages' memory safety models, namely C/C++.
It is not the case, not bad faith intended. To think it is a protest may be nearer.
Build in release a hello world, Build in release the example of this library (replacing the assert_eq by a println!("{}", zoned) or other ), or even a different library if it have a large dependence tree. Open on a text editor both files. The presence of the string messages for "unwrap" increased, right?
One can observe the code in this library take care of making reach the user the errors in most the parts of the library, so:
how was increased the string messages for "unwrap"? How can one know from were they came from? One ends up having to read all the dependencies^5, from were almost always a unwrap() reach the runtime of the release build.
Trying to figure this out as well... Tests have a bunch of .expect and .unwrap (which is to be expected), but core logic of the library doesn't seem to have any that seems they'll get in the way?
How could be erased those panic! methods that are used in most of Rust's libraries is something that may be is beyond the possible? beside is promoted from all the Rust's tutorials and reference code.
So much correctness in the Rust language just for to promote to all the community to crash the program from libraries without handling the error is something I can not understand.
I hope this philosophy do not reach the Linux kernel.