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

Tracking issue for Option::deref, Result::deref, Result::deref_ok, and Result::deref_err (feature: inner_deref) #50264

Closed
U007D opened this issue Apr 27, 2018 · 40 comments · Fixed by humanenginuity/rust#1 or #74948
Labels
A-result-option Area: Result and Option combinators B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@U007D
Copy link

U007D commented Apr 27, 2018

API

impl<T, E> Result<T, E> {
    fn as_deref(&self) -> Result<&T::Target, &E> where T: Deref;
    fn as_deref_err(&self) -> Result<&T, &E::Target> where E: Deref;
    fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> where T: DerefMut;
    fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> where E: DerefMut;
}

Implementation history

  • Implemented in Implement inner deref for Option and Result #50267 as:

    impl<T> Option<T> {
        fn deref(&self) -> Option<&T::Target> where T: Deref;
    }
    impl<T, E> Result<T, E> {
        fn deref(&self) -> Result<&T::Target, &E::Target> where T: Deref, E: Deref;
        fn deref_ok(&self) -> Result<&T::Target, &E> where T: Deref;
        fn deref_err(&self) -> Result<&T, &E::Target> where E: Deref;
    }
  • Renamed and extended in as_deref() and as_deref_mut() impls #59628 / Introduce as_deref to Option #62421:

    impl<T> Option<T> {
        fn as_deref(&self) -> Option<&T::Target> where T: Deref;
        fn as_deref_mut(&mut self) -> Option<&mut T::Target> where T: DerefMut;
    }
    impl<T, E> Result<T, E> {
        fn as_deref(&self) -> Result<&T::Target, &E::Target> where T: Deref, E: Deref;
        fn as_deref_ok(&self) -> Result<&T::Target, &E> where T: Deref;
        fn as_deref_err(&self) -> Result<&T, &E::Target> where E: Deref;
        fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target> where T: DerefMut, E: DerefMut;
        fn as_deref_mut_ok(&mut self) -> Result<&mut T::Target, &mut E> where T: DerefMut;
        fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> where E: DerefMut;
    }
  • Option methods stabilized in Stabilize Option::as_deref and Option::as_deref_mut #64708:

    impl<T> Option<T> {
        fn as_deref(&self) -> Option<&T::Target> where T: Deref;
        fn as_deref_mut(&mut self) -> Option<&mut T::Target> where T: DerefMut;
    }
  • Result methods pared down and renamed in Rename Result::as_deref_ok to as_deref #67930:

    impl<T, E> Result<T, E> {
        fn as_deref(&self) -> Result<&T::Target, &E> where T: Deref;
        fn as_deref_err(&self) -> Result<&T, &E::Target> where E: Deref;
        fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> where T: DerefMut;
        fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> where E: DerefMut;
    }
@U007D
Copy link
Author

U007D commented Apr 27, 2018

closed prematurely

@U007D U007D reopened this Apr 27, 2018
@Mark-Simulacrum Mark-Simulacrum added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. labels May 27, 2018
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Jul 30, 2018
bors added a commit that referenced this issue Jul 31, 2018
Implement inner deref for Option and Result

tracking issue: #50264
@RalfJung
Copy link
Member

I just found this useful! Thanks @Centril for pointing me here. :)

However, the name is a bit odd: It goes from &Option<T> to Option<T::Target>, e.g. from &Option<String> to Option<&str> -- that's just as much taking a reference as dereferencing one.

@U007D
Copy link
Author

U007D commented Dec 3, 2018

Ah, naming... :)

@oxalica
Copy link
Contributor

oxalica commented Dec 21, 2018

Oh, the method name collides Deref::deref, quite misleading.

I think as_deref could be better name.

@HeroicKatora
Copy link
Contributor

What about the name deref_inner for the case of Option and both arguments of Result; although the more though I put into it the more as_deref seems correct? Compared to other ref-utils this is missing the mut variants such as deref_ok_mut. I have mixed feelings about the api as a whole though, is there enough expressiveness advantage over a plain result.as_ref().map(|t| &**t)?

@durka
Copy link
Contributor

durka commented Jan 14, 2019 via email

@U007D
Copy link
Author

U007D commented Jan 14, 2019

@RalfJung correctly points out that there's as much ref going on as deref; As I think about this, it's about moving the outer ref onto the inner type, so how does as_inner_ref() sound to all of you? Avoids the name collisions that were pointed out, too.

Also agree with @HeroicKatora that the mut variations are currently missing. If this sounds good to the group, I'll get started on another pass over the next little while.

@HeroicKatora
Copy link
Contributor

HeroicKatora commented Jan 14, 2019

Hm, I see how this could be troubling at first, even more so with result.as_mut().map(|t| &mut **t). But in this case maybe the name should not be deref related afterall. While this maybe correct, one of the simplest issues where this API comes up might be finding a function of this type:

fn problem<'a, 'b>(&'a Option<&'b SomeType>) -> Option<&'a SomeType>

Another possibility would be to instead give those methods the type of

impl<'a, T> Option<&'a T> {
    fn deref<T>(self) -> Option<&'a T::Target> where T: Deref {
        self.map(|t| &**t)
    }
}

with usage opt.as_ref().deref(). This would be comparable with how the name Option::as_ref collides in relation to std::convert::AsRef and maybe still yield the discoverability as the inner workings of the map are probably the really hard issues for beginners. And maybe mention this example and usage in the documentation for as_ref() as well?

@nox
Copy link
Contributor

nox commented Mar 9, 2019

I just started making use of inert and this crate provides an Inert<T> type which implements both Deref<Target = T::Output> and AsRef<T::Output>.

Using Option::deref let me avoid a quite verbose line of code.

I have a reference to an Inert<Option<Dom<Node>>, which derefs to Option<Inert<Dom<Node>>>, where Inert<Dom<Node>> derefs to InertNode. I want Option<&InertNode>.

let parent_node: &Inert<Option<Dom<Node>>;

// Without Option::deref:
(**parent_node).as_ref().map(|node| &**node);

// With Option::deref:
parent_node.deref();

To summarise, this method helps a lot if you have a reference to something which derefs to Option<T> and also implements AsRef<Option<T>> and you want Option<&T::Target>.

@SimonSapin SimonSapin changed the title &Option<String> -> Option<&str> Tracking issue for Option::deref, Result::deref, Result::deref_ok, and Result::deref_err Mar 10, 2019
@SimonSapin SimonSapin added B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. and removed C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Mar 10, 2019
@SimonSapin
Copy link
Contributor

Turned into a tracking issue, since #[unstable] attributes point here.

@nox
Copy link
Contributor

nox commented Mar 11, 2019

About the name: As I'm mostly going to use it to replace a method named r in Servo, I would like to keep it short. The name deref is fine to me, and I could tolerate as_deref.

About the signature: I've yet to encounter a case where I'm fed something like Option<&String>, I usually take a reference to something owned somewhere, of type Option<String>. I would rather keep the current signature.

@joshtriplett
Copy link
Member

This seems great to me. This has been around for a long time; other than discussions around the name, is there any reason we shouldn't stabilize this?

@U007D
Copy link
Author

U007D commented Mar 16, 2019

@joshtriplett 1) the name and 2) the *Mut flavors of these

FYI, I've already started work on the *Mut side of things; I expect be able to have the new PR ready by the end of the month, if not before (sorry, my external commitments prevent me from being more precise than that at this point...).

In terms of naming, I've been kicking around (no particular order):

  • as_ref_deref/as_mut_deref (describes &**, without being too pedantic (i.e. avoid "as_ref_deref_deref/..."), and
  • as_inner_deref/as_inner_deref_mut (differentiates from deref/deref_mut and implies what kinds of transformations to expect)
  • as_inner_ref/as_inner_mut (same as above, but highlights the ref instead of the deref; also saves 2 chars of typing)

Personally, I feel the current deref/deref_mut is a bit misleading, given how it deref is (generally) used in the rest of std (I understand there are departures from this convention already, but I would prefer not to use that as a license to lower consistency further.) On the other hand, maybe this "convention" is all in my head... I'm open to your thoughts on this.

Given that, personally I am leaning slightly toward as_ref_deref/as_mut_deref because it is both distinct from deref and reasonably? descriptive about what it does.

Brevity is important, as is a (reasonably unambiguous) descriptive name. Please weigh in if you have thoughts any of these method names or ideas for others, and I'll try to put the zeitgeist into the upcoming PR.

@joshtriplett
Copy link
Member

joshtriplett commented Mar 16, 2019 via email

@OddCoincidence
Copy link
Contributor

Given we have cloned for Clone and soon copied for Copy, what about derefed?

@joshtriplett
Copy link
Member

joshtriplett commented Mar 21, 2019 via email

zmrow added a commit to zmrow/tough that referenced this issue Apr 17, 2020
This is a decent set of changes to tuftool. It fully removes the
KeySource enum in source.rs and instead uses the KeySource trait
from tough.

This commit also removes all SSM related code in favor of the
tough-ssm crate (which is a copy of this code).

It also removes the deref.rs file, as it is no longer need because
these features have stabilized in upstream Rust. See:
rust-lang/rust#50264
and
rust-lang/rust#64708
zmrow added a commit to zmrow/tough that referenced this issue Apr 27, 2020
This is a decent set of changes to tuftool. It fully removes the
KeySource enum in source.rs and instead uses the KeySource trait
from tough.

This commit also removes all SSM related code in favor of the
tough-ssm crate (which is a copy of this code).

It also removes the deref.rs file, as it is no longer need because
these features have stabilized in upstream Rust. See:
rust-lang/rust#50264
and
rust-lang/rust#64708
zmrow added a commit to zmrow/tough that referenced this issue Apr 30, 2020
This is a decent set of changes to tuftool. It fully removes the
KeySource enum in source.rs and instead uses the KeySource trait
from tough.

This commit also removes all SSM related code in favor of the
tough-ssm crate (which is a copy of this code).

It also removes the deref.rs file, as it is no longer need because
these features have stabilized in upstream Rust. See:
rust-lang/rust#50264
and
rust-lang/rust#64708
zmrow added a commit to zmrow/tough that referenced this issue Apr 30, 2020
This is a decent set of changes to tuftool. It fully removes the
KeySource enum in source.rs and instead uses the KeySource trait
from tough.

This commit also removes all SSM related code in favor of the
tough-ssm crate (which is a copy of this code).

It also removes the deref.rs file, as it is no longer need because
these features have stabilized in upstream Rust. See:
rust-lang/rust#50264
and
rust-lang/rust#64708
zmrow added a commit to zmrow/tough that referenced this issue Apr 30, 2020
This is a decent set of changes to tuftool. It fully removes the
KeySource enum in source.rs and instead uses the KeySource trait
from tough.

This commit also removes all SSM related code in favor of the
tough-ssm crate (which is a copy of this code).

It also removes the deref.rs file, as it is no longer need because
these features have stabilized in upstream Rust. See:
rust-lang/rust#50264
and
rust-lang/rust#64708
zmrow added a commit to zmrow/tough that referenced this issue May 19, 2020
This is a decent set of changes to tuftool. It fully removes the
KeySource enum in source.rs and instead uses the KeySource trait
from tough.

This commit also removes all SSM related code in favor of the
tough-ssm crate (which is a copy of this code).

It also removes the deref.rs file, as it is no longer need because
these features have stabilized in upstream Rust. See:
rust-lang/rust#50264
and
rust-lang/rust#64708
@dtolnay
Copy link
Member

dtolnay commented Jun 17, 2020

@rust-lang/libs:
@rfcbot fcp merge

Judging by https://grep.app/search?q=as_deref%28_mut%29%3F%5C%28%5C%29&regexp=true&filter[lang][0]=Rust, the Option::as_deref and Option::as_deref_mut methods have seen a fair amount of use.

I am interested in stabilizing these corresponding two methods on Result. The first was added in #50267 under the name deref_ok, then in #62421 renamed to as_deref_ok and augmented with as_deref_mut_ok, then in #67930 renamed to the current names as requested by #50264 (comment).

fn as_deref(&self) -> Result<&T::Target, &E> where T: Deref;
fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> where T: DerefMut;

Additionally I propose removing the remaining two methods tracked by this tracking issue. I expect these to be much less commonly applicable and they can be written instead as as_ref().map_err(Deref::deref) and as_mut().map_err(DerefMut::deref_mut).

fn as_deref_err(&self) -> Result<&T, &E::Target> where E: Deref;
fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> where E: DerefMut;

@rfcbot
Copy link

rfcbot commented Jun 17, 2020

Team member @dtolnay has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Jun 17, 2020
@RalfJung
Copy link
Member

RalfJung commented Jun 18, 2020

they can be written instead as as_ref().map_err(Deref::deref) and as_mut().map_err(DerefMut::deref_mut).

How discoverable is that, though? After all, the exact same argument applies to the methods that are being stabilized. Only stabilizing the Ok methods seems weirdly asymmetric.

RalfJung added a commit to RalfJung/rust that referenced this issue Jun 18, 2020
…=dtolnay

Improve document for `Result::as_deref(_mut)` methods

cc rust-lang#50264
@rfcbot rfcbot added the final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. label Jun 18, 2020
@rfcbot
Copy link

rfcbot commented Jun 18, 2020

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot removed the proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. label Jun 18, 2020
Manishearth added a commit to Manishearth/rust that referenced this issue Jun 18, 2020
…=dtolnay

Improve document for `Result::as_deref(_mut)` methods

cc rust-lang#50264
@rfcbot rfcbot added the finished-final-comment-period The final comment period is finished for this PR / Issue. label Jun 28, 2020
@rfcbot
Copy link

rfcbot commented Jun 28, 2020

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

The RFC will be merged soon.

@rfcbot rfcbot removed the final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. label Jun 28, 2020
@KodrAus KodrAus added A-result-option Area: Result and Option combinators Libs-Tracked Libs issues that are tracked on the team's project board. labels Jul 29, 2020
@RalfJung RalfJung changed the title Tracking issue for Option::deref, Result::deref, Result::deref_ok, and Result::deref_err Tracking issue for Option::deref, Result::deref, Result::deref_ok, and Result::deref_err (feature: inner_deref) Aug 1, 2020
@bors bors closed this as completed in 19ecce3 Aug 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-result-option Area: Result and Option combinators B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet