Skip to content

Tracking Issue for error_generic_member_access #99301

Description

@yaahc

View all comments

Feature gate: #![feature(error_generic_member_access)]

This is a tracking issue for the generic member access API on the error trait, which generalizes the pattern of fn source(&self) -> Option<&dyn Error> and fn backtrace(&self) -> Option<&Backtrace> into fn request_ref::<T>(&self) -> Option<&T>

Public API

// std::error

pub trait Error: Debug + Display {
    // existing API unchanged

    fn provide<'a>(&'a self, req: &mut Request<'a>) {}
}

pub struct Request<'a> { .. }

impl<'a> Request<'a> {
    pub fn provide_value<T>(&mut self, value: T) -> &mut Request<'a>
    where
        T: 'static;

    pub fn provide_value_with<T>(
        &mut self,
        fulfil: impl FnOnce() -> T,
    ) -> &mut Request<'a>
    where
        T: 'static;

    pub fn provide_ref<T>(&mut self, value: &'a T) -> &mut Request<'a>
    where
        T: 'static + ?Sized;

    pub fn provide_ref_with<T>(
        &mut self,
        fulfil: impl FnOnce() -> &'a T,
    ) -> &mut Request<'a>
    where
        T: 'static + ?Sized;

    pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
    where
        T: 'static;

    pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
    where
        T: 'static + ?Sized;
}

pub fn request_ref<'a, T: ?Sized + 'static>(err: &'a (impl Error + ?Sized)) -> Option<&'a T>;

pub fn request_value<T: 'static>(err: &(impl Error + ?Sized)) -> Option<T>;

Steps / History

Now tracked by @waynr in #99301 (comment)

Unresolved Questions

  • None yet.

Activity

  1. added
    T-libs-api[DEPRECATED; DO NOT USE]
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Jul 15, 2022
  2. dtolnay commented on Sep 5, 2022

    @dtolnay
    Member

    Hello from dtolnay/thiserror#185. I noticed it can be problematic for macros that Provider and Error both have a method named provide. I know this has been the case for other traits (Display and Debug both have a fmt method, for example) but one thing that makes the situation worse for provide is that we're commonly forced to rely on deref in order to call it, so fully-qualified method call syntax is not suitable to resolve the ambiguity:

    • In the case of Display, macros can write core::fmt::Display::fmt(&$thing, formatter) and that will always work, because even if $thing is something like Box<dyn Display>, there is an impl<T> Display for Box<T> where T: Display + ?Sized which makes it work.

    • However in the case of Error, writing core::error::Error::provide(&$thing, demand) is less good than $thing.provide(demand) because there is no impl<E> Error for Box<E> where E: Error + ?Sized. If $thing is Box<dyn Error + Send + Sync + 'static>, or anyhow::Error, these things rely on the deref done implicitly by .provide(demand) in order to deref to dyn Error + Send + Sync + 'static, which calling fully qualified core::error::Error::provide will not do.

    • The situation gets worse as other traits in the ecosystem follow the lead of Error and possibly add their own provide method. Maybe it's not so common that Provider and Error would be both in scope at the same time, but are we confident that Error and arbitrary other ecosystem trait won't be?

    Two proposals:

    1. There should be impl Provider for Box<dyn Error + …> in the standard library. This makes core::any::Provider::provide(&$thing, demand) accommodate more cases, but still not as good as having a deref.

    2. Is there someone who might be interested in pursuing a "fully qualified method call but with deref/autoref" RFC? The syntax thing.core::any::Provider::provide(demand) has been suggested for this in the past, and would eliminate the difficulty for macros that want a deref or autoref but also need to be robust to multiple traits having the same method name.

  3. JonasJebing commented on Oct 23, 2022

    @JonasJebing

    I agree, that

    a "fully qualified method call but with deref/autoref" RFC

    would be great.
    An immediate remedy would also be to rename Error::provide.
    The error_generic_member_access RFC and the dyno/provide_any RFC were already using Error::provide_context instead of Error::provide in their examples.
    I'd gladly create a PR to change the name if there are no objections.

  4. added a commit that references this issue on Nov 4, 2022
  5. robamler commented on Jan 21, 2023

    @robamler
    Contributor

    Not sure if this has been proposed before, but maybe an alternative to "fully qualified method call but with deref/autoref" could be that, in case of an ambiguity, trait method resolution favors traits that were introduced in inner scopes.

    Currently, the following code doesn't compile:

    fn foo(x: u32, formatter: &mut core::fmt::Formatter) {
        use core::fmt::{Display, Debug};
    
        { // Imagine this block was generated by a macro that only needs `Display` but not `Debug`.
            use core::fmt::Display; // currently leads to a warning: "the item `Display` is imported redundantly"
            x.fmt(formatter); // currently leads to an error: "multiple `fmt` found"
        }
    }

    The proposal would be to allow the above code, and to resolve x.fmt(formatter) to core::fmt::Display::fmt(&x, formatter) since Display was used in a strictly narrower scope than Debug.

    I don't think this would change any behavior in code that currently compiles since it would only disambiguate cases that are currently ambiguous. And it would allow macro authors to simply introduce a new scope and use any traits that their macros will need (this wouldn't leak any identifies to the outer scope since, already today, those uses are scoped to the inner block).

  6. nrc commented on Feb 22, 2023

    @nrc
    Member

    An easier solution would be to rename Error::provide. At one point it was provide_context and we should be able to find some other name for it.

  7. drmason13 commented on Apr 27, 2023

    @drmason13

    For what it's worth, provide_context feels like a good name for this method to me.

    Sure it's longer but it's more clear that it's about the error providing some sort of context to a user that comes from the concrete error type.

    Whereas a plain provide had me thinking "provide what?".

  8. jyn514 commented on May 16, 2023

    @jyn514
    Member

    An immediate remedy would also be to rename Error::provide.
    The error_generic_member_access RFC and the dyno/provide_any RFC were already using Error::provide_context instead of Error::provide in their examples.
    I'd gladly create a PR to change the name if there are no objections.

    @JonasJebing that sounds great! do you have time to follow up on that? :)

  9. waynr commented on Jul 15, 2023

    @waynr
    Contributor

    FYI for anyone subscribed to this issue hasn't been following #96024 or #113464 - I have volunteered to take on this issue to see what i can do to help push the generic member access work forward.

    Next steps for this issue include:

  10. waynr commented on Jul 15, 2023

    @waynr
    Contributor

    @rustbot claim

  11. yaahc commented on Jul 18, 2023

    @yaahc
    MemberAuthor
    • @yaahc is it possible for you to give me edit permissions for the description on this issue so i can keep the steps/history section updated? or should i just ping you whenever i need it updated? or maybe it would be simpler to open a new tracking issue?

    Not that I know of. The only way I can think of is via team membership since I think permissions are set up so that team members can usually edit any comments in the repo, for instance, I can edit your reply in this issue for whatever reason...

    Feel free to just ping me (zulip works best), I'll start by grabbing the next steps you added and vendoring them into the top level comment.

    Edit: alright, I've gone ahead and edited the todolist on the issue. Not sure if the provide_context rename is still relevant, lmk either way.

  12. 197 remaining items

  13. lygstate commented on Feb 24, 2026

    @lygstate
    Contributor

    I've been made aware that there is an open RFC for trait-to-trait casts, and I would like to know the opinion of @rust-lang/lang as to how likely it is to be accepted/implemented.

    Nobody in the libs-api team really likes the provider API and we would much prefer if there was a language-level solution to the problem of extracting arbitrary data out of a dyn Error.

    If it's frustrated, better not have it, we already deal with all kinds of fault of C for so many years 👍

  14. added
    I-lang-nominatedNominated for discussion during a lang team meeting.
    P-lang-drag-1Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang
    on Feb 25, 2026
  15. Amanieu commented on Feb 26, 2026

    @Amanieu
    Member

    RFC 3885 was discussed in the lang meeting and there was a lot of enthusiasm for it. As I've said before, the libs-api team strongly prefers language-level trait object casting to the provider API. However this fundamentally requires that someone put the work in to actually implement this feature. If anyone is interested then they should say so on the RFC thread.

    In the meantime I will cancel the FCP since we have a better alternative solution in sight.

    @rfcbot cancel

  16. rust-rfcbot commented on Feb 26, 2026

    @rust-rfcbot
    Collaborator

    @Amanieu proposal cancelled.

  17. removed
    proposed-final-comment-periodProposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off.
    disposition-mergeThis issue / PR is in PFCP or FCP with a disposition to merge it.
    on Feb 26, 2026
  18. yaahc commented on Mar 3, 2026

    @yaahc
    MemberAuthor

    For what it's worth, @arielb1 brought up a concern in zulip the other day is how a language level solution would interact generics+&dyn Error (and I think generally any error wrapping types that masquerade as their wrapped error).

    #t-libs > Pushing error_generic_member_access forward @ 💬

    To give a gist, if you have a function that takes an E: Error generic type and you pass in a &dyn Error that has already been erased then attempt to extract some context such as a Backtrace by casting the E: Error type to some accessor trait you'd likely get None since &dyn Error or any equivalent wrapper wouldn't necessarily or may not be able to implement the accessor traits implemented on the underlying erased error.

    This isn't necessarily a hard blocker IMO. I like the argument that this may be a positive pressure in that it discourages proxying error types, and it shouldn't break intertrait casts on subsequent source errors in the chain of errors. Also, notably it shouldn't affect the likes of Box<dyn Error> and anyhow/eyre given that they do not themselves implement the Error trait.

    Provider avoids this by allowing proxying types to directly invoke the provide impl of their wrapped errors.

    Either way though I think this is an important factor to consider when deciding which approach to prefer.

  19. added
    I-lang-radarItems that are on lang's radar and will need eventual work or consideration.
    and removed
    I-lang-nominatedNominated for discussion during a lang team meeting.
    P-lang-drag-1Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang
    on Mar 4, 2026
  20. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    and removed
    T-libs-api[DEPRECATED; DO NOT USE]
    on Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCI-lang-radarItems that are on lang's radar and will need eventual work or consideration.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions