In light of recent events at CloudFlare, I think it is poignant to open a discussion again on if rust should rename Option::unwrap and Result::unwrap.
Pros:
Option::unwrap() does not reflect the possibility of panic, Option::unwrap_or_panic() would be in-line with Option::unwrap_or* family of functions. (Same for Result)
Having it be a longer name makes it more annoying for developers to use, and thus, discourage it (This might be a con though)
Cons:
Obviously a gigantic change
160 mentions of unwrap in rust-lang/book
3.5k (!!!!) calls to unwrap in rust-lang/rust
I do however believe that the transition could be smoothed over by the fact that, rust has excellent compatibility model with editions. With editions, there is no pressure to churn as fast. And given cargo fix --edition migration tool, migration for Rust users should be as easy as invoking this. For rust language developers themselves though, I could see how this would create an unreasonable amount of extra work for little to no benefit, as I am not a rust core developer myself, I can not judge how much work it actually would be, but 3.5k mentions does sound like an awful lot
Note that I do not believe that the rename would've prevented the CloudFlare incident, but it is an opportune time to bring it up.
I think this is something where most people can agree that unwrap is not the best name for it, but also something where renaming it is a giant effort. I agree that it's not worth it. If it was 2012, sure, but not in 2025.
Rust developers quickly familiarize themselves with what unwrap means, so I don't think the name really leads to many problems in practice.
I want to emphasize that this it not really what I think about when I think about the downsides of a rename like this. In fact, I'd consider this one specific task effectively free. It doesn't really weigh on me, at all, in this case.
What weighs on me is churn and confusion.
Churn comes from projects outside of the Rust project migrating to new Rust versions where the old name is deprecated. A change like this can indeed thankfully be automated, but there are likely many places where tooling won't get it right. I'm thinking about documentation in particular. And whenever I've used this sort of automated tooling in the past, it usually comes with little papercuts. Like, maybe doctests are updated, but they aren't reformatted (because that's an unstable rustfmt feature). Moreover, deprecation usually has to be done in phases. For folks maintaining older MSRVs, this usually means doing an allow(deprecated) somewhere. Since unwrap() is a very commonly used routine, you'll probably need to apply it at the crate level. Only once the MSRV is new enough to include the rename will unwrap() actually disappear.
Any single change doesn't impact churn too much. But when we do deprecations as frequently as we do, it definitely adds up. So my default position is generally against deprecations on their face.
Another strong reason against this is the confusion that I think is likely to result. And this is especially relevant to routines like unwrap() and expect() that have pervasive usage. That is, even following the rename, and then waiting N years for crates with old MSRVs to migrate, there will still be countless materials using unwrap() and expect() that will simply never get updated. New users will see those and they will get confused. Because where as before they could just use unwrap() and be done with it, they now have to deal with a choice between unwrap() and some new routine. It seems small, but I believe strongly that this introduces friction in understanding and writing code.
For unwrap() and expect() in particular, these problems are magnified because of how widely used they are.
Of course, these sorts of renames are sometimes worth doing. Particularly when the routines aren't as pervasively used or when there are stronger downsides with the existing name.
I want to also point out that I am aware of Stuart Feldman's cautionary tale about tabs inside Makefiles:
Why the tab in column 1? Yacc was new, Lex was brand new. I hadn't tried either, so I figured this would be a good excuse to learn. After getting myself snarled up with my first stab at Lex, I just did something simple with the pattern newline-tab. It worked, it stayed. And then a few weeks later I had a user population of about a dozen, most of them friends, and I didn't want to screw up my embedded base. The rest, sadly, is history.
And:
I used tabs because I was trying to use Lex (still in first
version) and had trouble with some other patterns.
(Make was written over a weekend, rewritten the next weekend ...)
So I gave up on being smart and just used a fixed pattern (^\t)
to indicate rules.
Within a few weeks of writing Make, I already had a dozen friends
who were using it.
So even though I knew that "tab in column 1" was a bad idea, I
didn't want to disrupt my user base.
So instead I wrought havoc on tens of millions.
But Rust is well beyond "a few users." I can appreciate the idea that most of the people who will come to learn Rust have never even heard of it today is another take on a similar perspective. That is, while a change like this will cause pain now, and might even continue to cause pain 5 years later, eventually that pain will reduce over time. And in exchange, we will get a better name for a very frequently used routine. (I concede the point on the existence of a better name in order to focus discussion on what I believe are the salient points. But I actually do like unwrap() as a name.) So when I say I'm opposed to this change, I am taking all of this into account and come down on the side of "it's not worth it."
Note that based on what was shown in the blog post the unwrap had basically nothing to do with the CloudFlare issue. If it had returned an error instead of crashing it would still not be servicing the requests. And the older implementation demonstrated this.
This is the most important part of the whole thing to me. Exactly how it happened is largely irrelevant -- the same thing (but maybe worse) could have happened completely without unwrap if, for example, the list in question was being processed recursively and the greatly increased size of the list meant it hit a stack overflow that it never had before.
There are good learnings from the RCA, but focusing on unwrapspecifically is a distraction.
We should have good tools for correctness checking -- I'm really excited by the contracts work, for example -- but the CloudFlare post itself really doesn't change my opinion on unwrap in any way. I'm still happy it's downtime and not a new heartbleed.
(And +1 to what burntsushi said about the costs -- the PR to add a new name in library is trivial. It's the impact everywhere else that's the problem.)
I'm also not convinced it's worth it. It is true that we have the tools to make it happen: we have editions and cargo fix --edition, etc., but that's a very heavy tool that we should use very carefully. The amount of tutorials, books, example code, etc. that will all be outdated is huge, for example.
Renaming just these methods doesn't "fix" Rust. There are plenty of other methods on Result and Option that we would probably have named differently if we had a time machine. And plenty of other things in the rest of the standard library that aren't perfect. Imagine if at every release we'd rename a few methods through some edition-like mechanism. "unwrap is now or_panic!" today, "String is now StrBuf!" next month, then "str::chars() is now str::codepoints()!", and so on. That would be a pretty bad experience for Rust users! The language would feel very unstable!
It's a good argument that Rust is still growing exponentially and that all Rust code in existence today is only a fraction of all Rust code that is yet to be written. That might be part of a convincing argument to make changes like this as part of an edition. But since that's not a tool we want to use too often, such changes should be done as part of a bigger coherent whole with a clear plan and a discussion/tradeoff that considers the impact on the Rust ecosystem, not just as a quick "let's just rename this one method" kind of change.
I want to emphasize that this it not really what I think about when I think about the downsides of a rename like this. In fact, I'd consider this one specific task effectively free. It doesn't really weigh on me, at all, in this case.
I appear to have severely overestimated the difficulty then
Churn comes from projects outside of the Rust project migrating to new Rust versions where the old name is deprecated. [....] And whenever I've used this sort of automated tooling in the past, it usually comes with little papercuts
Oh, I was hoping the process would be almost fully automatic, fair enough!
But since that's not a tool we want to use too often, such changes should be done as part of a bigger coherent whole with a clear plan and a discussion/tradeoff that considers the impact on the Rust ecosystem, not just as a quick "let's just rename this one method" kind of change.
I think that's a great idea! Collect all of these and rename them together, as a package, with proper announcements and migrations.
I am still convinced it should happen at some point. Perhaps not right now, almost certainly as a part of a bigger package though, Rust 2.0 anyone? Although I am aware of my own bias for underestimating large refactoring costs and for unnecessary perfectionism, so I don't think I am fully pragmatic in this.
If I knew of a reasonable way to make that happen, I'd have submitted a PR or RFC instead of posting it as a 'hot take' on social media.
I'm skeptical if just renaming the method would even fix anything. Whether it's called or_panic(), unwrap() or yolo(), it would remain the thing that people call when they are prototyping, or when - at the time - the thing is guaranteed to be Ok() but the compiler can't prove it (and then later that assumption changes).
So to "fix unwrap", we'd have to reduce the need for unwrap in the first place.
For example I had some code that did a lot of serde_json::Value accesses through the Index operator and unwraps. Once let-else became available it was often sufficiently-ergonomic to replace those panicky accesses.
Though in the particular cloudflare case it's not clear that we would have needed anything at all. Their method already had a Result return type, they could have propagated the error and handled it.
It's not even a tooling issue, clippy already has lints for that.
Why they didn't use that? Unknown.
Hold on, that's not quite what I'm suggesting. The question remains at what point it reaches a level where it is actually worth it. Even if we can somehow 'fix' everything in the standard library all at once and make it all 'perfect', I'm not at all convinced it's worth it. There simply isn't that much wrong with the standard library. It has plenty of small annoyances, but I don't think they add up to something significant enough for an big edition-like overhaul to be worth it.
It's an interesting question whether that might be different in the future. Naturally, the amount of papercuts and small mistakes in the standard library will grow over time. Do we expect it to reach a point where it might be worth having a new 'edition' of the standard library? Probably not? Maybe many years from now?
I think the closest reasonable rephrasing of this request would be to by default lint/warn on unwrap usage (outside of tests and mx.lock().unwrap() and whatever). Perhaps only lib crates should warn by default.
This is something I do by (personal) default on my projects.
If the official team believes that deprecating Option::unwrap, Option::expect, Result::unwrap, and Result::expect is feasible, then I recommend rewriting the original uses of unwrap and expect in various materials as:
if option.is_none() {
panic!("none");
}
if Err(err) = result {
panic!("err: {}", err);
}
This fits perfectly with Rust’s philosophy: the discouraged way of writing things is intentionally more cumbersome.
I am aware of this position, but the question is more what the language default should be. Especially for people relatively new to rust, I think I would prefer the default were to lint against most unwraps. More experienced users can always #[allow or #![allow it along with the rest of their particular litany of warnings and clippies.
I suppose I can't answer whether or not this would just teach people to .expect(""), and perhaps people learning the language are normally starting with a particular clippy/warning setup that helps more than the default. Hopefully I'm not just elevating a preference to thinking it should be the way things are.
This is my feeling. While yes, it would've been great to do this a decade ago, we could easily say the same thing in another decade when there's far more Rust code in existence.
Regarding MSRV, I don't see that as a huge issue given that the newly-introduced methods would presumably exist before the existing ones are deprecated, let alone made inaccessible (effectively removed) in an edition. Look at std::u32, for example. It's been "deprecated in the future" for a long time, but we still aren't even warning on that by default.
I fully agree that this should not be done lightly or on a whim, but I also don't think saying "we will never use editions to rename something" is the right take. We just need to figure out where the threshold is and if this meets it.
Wrong decisions were and inevitably will continue to be made; I view it as similarly inevitable that we will feel the need to rename something nontrivial in the future, whether it be unwrap or something else. Let's take our time to determine the proper process to do so and implement the relevant mechanisms in the compiler.