Repository: rust
Issue: Tracking Issue for Provider API
Labels: B-RFC-approved,T-libs-api,B-unstable,B-RFC-implemented,C-tracking-issue

<!--
Thank you for creating a tracking issue!

Tracking issues are for tracking a feature from implementation to stabilization.

Make sure to include the relevant RFC for the feature if it has one.

If the new feature is small, it may be fine to skip the RFC process. In that
case, you can use use `issue = "none"` in your initial implementation PR. The
reviewer will ask you to open a tracking issue if they agree your feature can be
added without an RFC.
-->

Feature gate: `#![feature(provide_any)]`

This is a tracking issue for [RFC 3192](https://github.com/rust-lang/rfcs/pull/3192) 

> This RFC proposes extending the [`any` module](https://doc.rust-lang.org/nightly/std/any/index.html) of the core library with a generic API for objects to provide type-based access to data. (In contrast to the existing APIs which provides type-driven downcasting, the proposed extension integrates downcasting into data access to provide a safer and more ergonomic API).

The initial motivating use case for this API is to provide the necessary functionality to add [generic member access](https://github.com/rust-lang/rfcs/pull/2895) to the `Error` trait to generalize extracting context like `Backtrace` and to make it possible to move the `Error` trait into `core` while leaving `Backtrace` in `std`.

### Public API

```rust
// core::any
pub trait Provider {
    fn provide<'a>(&'a self, demand: &mut Demand<'a>);
}

pub fn request_value<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<T>
where
    T: 'static;

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

#[repr(transparent)]
pub struct Demand<'a>(_);

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

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

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

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

    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: ?Sized + 'static,
}

impl<'a> fmt::Debug for Demand<'a> {}

// core::error
impl<E> Provider for E
where
    E: Error + ?Sized;
```

### Steps / History

<!--
For larger features, more steps might be involved.
If the feature is changed later, please add those PRs here as well.
-->

- [x] Implementation: https://github.com/rust-lang/rust/pull/91970
- [ ] Delete the `Provider` trait and merge its functionality into `Error`.
- [ ] Pick either `demand` or `request` and use that name consistently. 
- [ ] LLVM is unable to optimize multiple `.provide_*` calls into a switch table because each call fetches the type id from `Erased::type_id` separately each time and the compiler doesn't know that these calls all return the same value. This should be fixed. See https://github.com/rust-lang/rfcs/pull/3192#issuecomment-1018020335 for one possible solution (although alternative solutions may be possible).
- [ ] Final comment period (FCP)
- [ ] Stabilization PR

<!--
Once the feature has gone through a few release cycles and there are no
unresolved questions left, the feature might be ready for stabilization.

If this feature didn't go through the RFC process, a final comment period
(FCP) is always needed before stabilization. This works as follows:

A library API team member can kick off the stabilization process, at which point
the rfcbot will ask all the team members to verify they agree with
stabilization. Once enough members agree and there are no concerns, the final
comment period begins: this issue will be marked as such and will be listed
in the next This Week in Rust newsletter. If no blocking concerns are raised in
that period of 10 days, a stabilzation PR can be opened by anyone.
-->

### Unresolved Questions

<!--
Include any open questions that need to be answered before the feature can be
stabilised. If multiple (unrelated) big questions come up, it can be a good idea
to open a separate issue for each, to make it easier to keep track of the
discussions.

It's useful to link any relevant discussions and conclusions (whether on GitHub,
Zulip, or the internals forum) here.
-->

- [ ] Should the APIs be named `demand_*` or `request_*`?

<!-- TRIAGEBOT_START -->

<!-- TRIAGEBOT_ASSIGN_START -->

<!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"waynr"}$$TRIAGEBOT_ASSIGN_DATA_END -->

<!-- TRIAGEBOT_ASSIGN_END -->
<!-- TRIAGEBOT_END -->