Skip to content

Tracking issue for Option::expect_none(msg) and unwrap_none() #62633

@cuviper

Description

@cuviper
Member
impl<T: fmt::Debug> Option<T> {
    pub fn expect_none(self, msg: &str);
    pub fn unwrap_none(self);
}

Steps:

Activity

added
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
B-unstableBlocker: Implemented in the nightly compiler and unstable.
C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
on Jul 12, 2019
jfrimmel

jfrimmel commented on Oct 2, 2019

@jfrimmel
cuviper

cuviper commented on Oct 2, 2019

@cuviper
Author
jfrimmel

jfrimmel commented on Oct 2, 2019

@jfrimmel
cuviper

cuviper commented on Apr 20, 2020

@cuviper
MemberAuthor

I guess it could use more in-repo callers? I do see that rustc_middle and rustc_mir are using expect_none, at least. Grepping for assert.*is_none shows a lot more possibilities, but maybe some of those would not like the added code to Debug the value in the panic message.

aclysma

aclysma commented on May 16, 2020

@aclysma

I'd love to see this go to stable.. I'm having to do this:

let old_value = self.values.insert(key, value);
assert!(old_value.is_none());

And I'd much rather do

self.values.insert(key, value).unwrap_none();
dtolnay

dtolnay commented on Jun 9, 2020

@dtolnay
Member

In the stabilization PR it was raised that &self may be more appropriate and flexible in these signatures than self. Do potential users here have a preference for either?

RustyYato

RustyYato commented on Jun 9, 2020

@RustyYato
Contributor

You can use as_ref if you need a reference. Also, we should be consistent between our functions (Option::unwrap).

added
A-result-optionArea: Result and Option combinators
Libs-SmallLibs issues that are considered "small" or self-contained
on Jul 29, 2020

136 remaining items

SOF3

SOF3 commented on Nov 25, 2022

@SOF3
Contributor

The problem is that this issue is fundamentally an XY problem, where the real problem is the lack of postfix macros but we tried to solve this problem by bloating the standard library instead.

RalfJung

RalfJung commented on Nov 25, 2022

@RalfJung
Member
SOF3

SOF3 commented on Nov 25, 2022

@SOF3
Contributor

@RalfJung yes, I think unwrap and expect are bloat as well. They should have simply been

value.expect!()
value.expect!("expect message")
value.expect!("formatted {expect} {}", message)
zdivelbiss

zdivelbiss commented on Apr 7, 2023

@zdivelbiss
  • unwrap_none is not the right name, as there's nothing inside a None to unwrap.

This statement doesn't really make any sense. You aren't unwrapping the None, you're unwrapping the Option, which may or may not contain Something. Unless the libs team or someone else explicitly specifies what 'unwrap' to be consistent with that argument, the 🎁 analogy used earlier holds: unwrapping a present and finding nothing was still unwraping the present.

  • As a method that only asserts something, it doesn't fit any existing pattern. It'd be a new pattern that would also fit things like i32::assert_positive(), Vec::assert_empty(), bool::expect_true(), f64::assert_finite(), etc. This is not a direction we want to pursue. (Or at least not without an RFC.)

I'm skeptical of this at its face value. The notion of unwrap_ is fundamentally the concept of "unwrap this container, expect this valuedness, then return what was inside":

  • unwrap() -> unwrap and expect Some()/Ok(), and return the value
  • unwrap _err() -> unwrap Err(), and return the value
  • unwrap_none() -> unwrap None, and return the value (in this case, nothing, which has a value in Rust!)
  • assert_eq!(option, None); already shows the value inside the Some in the panic message. (Note that unlike in C and C++, asserts in Rust are unconditional and also included in release builds.)

This is simply not ergonomically consistent with how one expects to assert the valuedness of the container enums. Unless there are plans to deprecate the panicking unwrap_ APIs, then this semantic inconsistency will continue to draw new users to this issue, only to be disappointed by unclear and inconsistent logic from the rust teams.

During our discussion, the idea of an Option::err_or was brought up. In examples where panicking on a Some makes sense, the Some is considered an error. So, a function that would convert an Option::Some to a Result::Err might make sense in some of those cases, such that that Result can then be handled in the usual ways, such as by unwrapping it. We didn't discuss this option in detail, so there's no concensus on this yet, but it might be an interesting direction to explore separately from unwrap_none/expect_none.

This seems like skirting around the reality that the expectation of a semantic way to inline-assert the valuedness of a container has already been proposed in this issue. You certainly can introduce the function discussed in this thread as an entirely new unwrapping API separate from the existing unwrapping APIs, but it feels like arbitrarily beating around the bush of this issue. Really, this is functionally another inline syntax for Option::ok_or().unwrap_err().

Overall, reading this, I wasn't particularly satisfied with the responses, justifications, or in general the way this issue was handled. There was next to no communication while the issue was being reviewed, followed by subjective arguments, followed (finally) by an actual discussion of the logical reasoning of the libs team.

It really just seems like the team that voted on this doesn't like the idea of unwrapping an empty 🎁.

buzmeg

buzmeg commented on Apr 17, 2023

@buzmeg

Quoting @SOF3

The problem is that this issue is fundamentally an XY problem, where the real problem is the lack of postfix macros but we tried to solve this problem by bloating the standard library instead.

Which would be fine, except that 5 years on we don't have a solution for X OR Y. And none of the alternatives mentioned to solve this have moved even slightly over 5 years. And, if postfix macros didn't get resolved given their usefulness for "async" which everybody on the core team was totally obsessed with, they are never going to move.

So, I'm so glad you maintained your vaunted "language purity", but, in the meantime, users of the language are still stuck exactly where they started.

That's fine. Many of us can take a hint and understand that it is time to move on from Rust.

mankinskin

mankinskin commented on Apr 17, 2023

@mankinskin

To contrast, I find there is value in a clean code base and principled design. But I think pragmatism is one of the most important principles which should drive language design. And I personally don't really have any validated reasons on my list about why unwrap_none or expect_none would be bad to have. If there is any reason why the existence of these functions could reduce the quality of the Rust language, then maybe we should start talking about those instead of why it might be a good idea to have these. They are obviously useful, so if there are no reasons why this should be blocked it should simply be added to a library and eventually stabilized.

m-ou-se

m-ou-se commented on Apr 18, 2023

@m-ou-se
Member

The notion of unwrap_ is fundamentally the concept of "unwrap this container, expect this valuedness, then return what was inside"

Sure.

This statement doesn't really make any sense. You aren't unwrapping the None, you're unwrapping the Option, which may or may not contain Something.

To unwrap the Option, we already have a method: .unwrap(). In an Option::None, there is nothing to unwrap, so it panicks.

unwrap None, and return the value (in this case, nothing, which has a value in Rust!)

.unwrap() is about getting the contents of the Some out. But .unwrap_none() isn't about getting the contents of the None out, because there are none. Sure, you can represent that as (), but if you want a (), you don't need to call this method. The only reason you'd ever call .unwrap_none() is as an assertion, a conditional panic, not as a way to access a value. So, it'd basically be a .panic_if_some() or .assert_none().

So then the question is whether we want such methods. I don't think we do, because we also don't have anything like i32::assert_nonzero(), bool::panic_if_false(), or Vec::unwrap_empty(), and so on. All of those assertions you'd write using an assert macro or a panic inside an if. I don't think there is enough reason to give Option::is_none() special treatment.

So, I'm so glad you maintained your vaunted "language purity", but, in the meantime, users of the language are still stuck exactly where they started.

Many of us can take a hint and understand that it is time to move on from Rust.

I don't think Rust is very "pure". I also don't think users are "stuck". There are many simple ways to express a check for None, so I doubt this is really a blocker for anyone. Maybe there's even a crate with an extension trait to add .panic_if_…() to various common types.

If there is any reason why the existence of these functions could reduce the quality of the Rust language, them maybe we should start talking about those [..]

They are obviously useful, so if there are no reasons why this should be blocked [..]

Many reasons have been given in this thread. I'm not sure what I can add at this point without just repeating things that have already been said.

m-ou-se

m-ou-se commented on Apr 18, 2023

@m-ou-se
Member

Overall, reading this, I wasn't particularly satisfied with the responses, justifications, or in general the way this issue was handled. There was next to no communication while the issue was being reviewed, …

As I highlighted here, we're all just volunteers working on the standard library next to many other tasks, so while we'll try our best to communicate everything as clearly as possible, it sometimes takes longer than you might hope for.

… followed by subjective arguments, …

I'm afraid that API design will always be based on subjective arguments. There's no objective right or wrong way to design a library.

… followed (finally) by an actual discussion of the logical reasoning of the libs team.

I'm not sure what you expect from us at this point. Many arguments have been given and thoroughly explained over the past few years, and it just seems like we're going in circles now. :/

pronebird

pronebird commented on Jun 29, 2024

@pronebird

I'm not sure what you expect from us at this point.

The unexpected. I mean, literally, the unexpect(<msg>) to mirror already available expect()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-result-optionArea: Result and Option combinatorsB-unstableBlocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCLibs-SmallLibs issues that are considered "small" or self-containedLibs-TrackedLibs issues that are tracked on the team's project board.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.disposition-closeThis PR / issue is in PFCP or FCP with a disposition to close it.finished-final-comment-periodThe final comment period is finished for this PR / Issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @steveklabnik@cuviper@trevyn@aclysma@RalfJung

      Issue actions

        Tracking issue for Option::expect_none(msg) and unwrap_none() · Issue #62633 · rust-lang/rust