Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[�CP] Option: add by-{ref,mut} variants to the most pervasive adapters #98536

Conversation

danielhenrymantilla
Copy link
Contributor

@danielhenrymantilla danielhenrymantilla commented Jun 26, 2022

Add by-ref & by-mut variants to the most pervasive adapters of Option

API Overview

#[unstable(feature = "option_borrowing_adapters",)]
impl<T> Option<T> {
    pub fn unwrap_ref(&self) -> &T;
    pub fn unwrap_mut(&mut self) -> &mut T;

    pub fn expect_ref(&self, msg: &str) -> &T;
    pub fn expect_mut(&mut self, msg: &str) -> &mut T;

    pub fn map_ref<'r, U, F>(&'r self, f: F) -> Option<U>
    where
        F: FnOnce(&'r T) -> U,
    ;
    pub fn map_mut<'r, U, F>(&'r mut self, f: F) -> Option<U>
    where
        F: FnOnce(&'r mut T) -> U,
    ;

    pub fn and_then_ref<'r, U, F>(&'r self, f: F) -> Option<U>
    where
        F: FnOnce(&'r T) -> Option<U>,
    ;
    pub fn and_then_mut<'r, U, F>(&'r mut self, f: F) -> Option<U>
    where
        F: FnOnce(&'r mut T) -> Option<U>,
    ;
}

Questions

  • Should we also offer some of these for Result?

    • In practice borrowing Options is very typical due to struct fields having them, whereas Result is almost exclusively used by-value / in an owned fashion. Thence left for a potential follow-up PR.
  • would there be other Option methods that could benefit from _{ref,mut} flavors (e.g., .unwrap_or{,_else}())?

    • If so, follow-up PRs could easily add those
  • bikeshedding names etc.

    • To be left for stabilization, should it ever happen (this is just a [�CP] proposal, for nightly experimentation. It may not be stabilized or even be removed from future nightlies should the experimentation yield mixed results).

Alternatives

  • Have a .map() (and so on) in-prelude extension trait for &Option and &mut Option, so that borrowed_opt.map(…) (and so on) would Just Work™ (but then for a struct field we'd need some postfix borrowing thing, such as borrowed_struct.field&.map(…) or what not… which is way beyond the scope of this API suggestion);

@rustbot modify labels: +T-libs-api -T-libs

@rustbot rustbot added the T-libs Relevant to the library team, which will review and decide on the PR/issue. label Jun 26, 2022
@rust-highfive
Copy link
Collaborator

Hey! It looks like you've submitted a new PR for the library teams!

If this PR contains changes to any rust-lang/rust public library APIs then please comment with @rustbot label +T-libs-api -T-libs to tag it appropriately. If this PR contains changes to any unstable APIs please edit the PR description to add a link to the relevant API Change Proposal or create one if you haven't already. If you're unsure where your change falls no worries, just leave it as is and the reviewer will take a look and make a decision to forward on if necessary.

Examples of T-libs-api changes:

  • Stabilizing library features
  • Introducing insta-stable changes such as new implementations of existing stable traits on existing stable types
  • Introducing new or changing existing unstable library APIs (excluding permanently unstable features / features without a tracking issue)
  • Changing public documentation in ways that create new stability guarantees
  • Changing observable runtime behavior of library APIs

@rustbot rustbot added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Jun 26, 2022
@rust-highfive
Copy link
Collaborator

r? @Mark-Simulacrum

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 26, 2022
@rustbot rustbot removed the T-libs Relevant to the library team, which will review and decide on the PR/issue. label Jun 26, 2022
@joshtriplett
Copy link
Member

I don't think we should have more wrappers around the panicking unwrap and expect. It's already hard to search for and remove those, because you have to exclude non-panicking functions like unwrap_or/unwrap_or_else. I currently do that by doing a whole-word search for unwrap, but that wouldn't catch unwrap_ref or unwrap_mut.

No objections to the and_then or map variants. I do wonder if they carry enough weight, though. Do you have numbers for how common a pattern they are? Even if they are common, we have a lot of helper functions on Option and Result, and I'm wondering if the sheer weight of them is a learnability/readability burden.

@Mark-Simulacrum
Copy link
Member

I agree with @joshtriplett; I think we already have more adapters on Option/Result than is probably really necessary, and I'd rather not add new ones to be fully generic over ref/ref-mut. It's possible that with rust-lang/lang-team#162 we might be able to do so at no name/discovery cost, if that initiative materializes, but for now I think they're pretty unlikely to pull their weight. (And even with that initiative I think it's an unclear win).

r? @joshtriplett since I'd personally not r+ this but T-libs-api is the team to make a decision here

@the8472
Copy link
Member

the8472 commented Jun 26, 2022

Since the existing methods already are orthogonal and composable (via as_ref and as_mut) and the Option API is quite big for such a simple container and that is its own API (not a trait that generalizes to many things) I already feel a bit of friction mixing up its methods.
Adding more API surface would make the haystack larger for me.

makes it easier for beginners struggling with "use of owned values" and navigating stdlib docs (https://doc.rust-lang.org/std) to know what to reach for (before understanding the full generalization to calling the generic .as_{ref,mut}() adapters beforehand).

Adding more API surface to handle a transient learning hurdle seems not great to me, especially since it creates its own hurdle (making Option a bigger thing to learn). Imo that's better solved through better documentation or teaching materials? Maybe a cheat-sheet/dense table? "I havea an X, I want to do Y and get a Z" -> use option.foo().bar)

Currently rustdoc is bad at providing this kind of mechanical overview. In the expanded view you get the whole doc comment. In the collapsed view you get the signature (with where clauses, which can be a lot to take in) but zero explanation. The left-aligned formatting also makes it more difficult to scan for return values.

I think javadoc method summary tables would provide more utility here. They allow quickly scanning for signatures that have the right shape and provide the headline summary of the method without all the details.

@danielhenrymantilla
Copy link
Contributor Author

It looks like I may have misjudged the pervasiveness of these patterns, and/or their convenience: they may indeed not carry enough weight after all.

@danielhenrymantilla danielhenrymantilla deleted the option-borrowing-adapters branch June 26, 2022 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants