about summary refs log tree commit diff
diff options
context:
space:
mode:
authorwayne warren <wayne.warren.s@gmail.com>2023-07-06 10:53:52 -0600
committerwayne warren <wayne.warren.s@gmail.com>2023-08-13 13:07:53 -0600
commita646b3996510fb79a8fd4701f888542e9b280504 (patch)
tree3594f24b64b7cf353df9e1a9ee09c8f64c2fd2be
parent644e8068cbffef6428d1970fe50a4a863079ee54 (diff)
downloadrust-a646b3996510fb79a8fd4701f888542e9b280504.tar.gz
rust-a646b3996510fb79a8fd4701f888542e9b280504.zip
core/any: remove Provider trait
* remove `impl Provider for Error`
* rename `Demand` to `Request`
* update docstrings to focus on the conceptual API provided by `Request`
* move `core::any::{request_ref, request_value}` functions into `core::error`
* move `core::any::tag`, `core::any::Request`, an `core::any::TaggedOption` into `core::error`
* replace `provide_any` feature name w/ `error_generic_member_access`
* move `core::error::request_{ref,value} tests into core::tests::error module
* update unit and doc tests
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/sync.rs2
-rw-r--r--library/core/src/any.rs587
-rw-r--r--library/core/src/error.rs735
-rw-r--r--library/core/tests/any.rs62
-rw-r--r--library/core/tests/error.rs66
-rw-r--r--library/core/tests/lib.rs4
-rw-r--r--library/std/src/error.rs13
-rw-r--r--library/std/src/error/tests.rs4
-rw-r--r--library/std/src/lib.rs1
10 files changed, 736 insertions, 739 deletions
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 80681a7a7cf..cb8691aac13 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -138,7 +138,6 @@
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(pattern)]
 #![feature(pointer_byte_offsets)]
-#![feature(provide_any)]
 #![feature(ptr_internals)]
 #![feature(ptr_metadata)]
 #![feature(ptr_sub_ptr)]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 6c701225a84..e2a2fe932ab 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -3575,7 +3575,7 @@ impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
         core::error::Error::source(&**self)
     }
 
-    fn provide<'a>(&'a self, req: &mut core::any::Demand<'a>) {
+    fn provide<'a>(&'a self, req: &mut core::error::Request<'a>) {
         core::error::Error::provide(&**self, req);
     }
 }
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 277c2f76a08..8f5404d9713 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -83,72 +83,6 @@
 //! }
 //! ```
 //!
-//! # `Provider` and `Demand`
-//!
-//! `Provider` and the associated APIs support generic, type-driven access to data, and a mechanism
-//! for implementers to provide such data. The key parts of the interface are the `Provider`
-//! trait for objects which can provide data, and the [`request_value`] and [`request_ref`]
-//! functions for requesting data from an object which implements `Provider`. Generally, end users
-//! should not call `request_*` directly, they are helper functions for intermediate implementers
-//! to use to implement a user-facing interface. This is purely for the sake of ergonomics, there is
-//! no safety concern here; intermediate implementers can typically support methods rather than
-//! free functions and use more specific names.
-//!
-//! Typically, a data provider is a trait object of a trait which extends `Provider`. A user will
-//! request data from a trait object by specifying the type of the data.
-//!
-//! ## Data flow
-//!
-//! * A user requests an object of a specific type, which is delegated to `request_value` or
-//!   `request_ref`
-//! * `request_*` creates a `Demand` object and passes it to `Provider::provide`
-//! * The data provider's implementation of `Provider::provide` tries providing values of
-//!   different types using `Demand::provide_*`. If the type matches the type requested by
-//!   the user, the value will be stored in the `Demand` object.
-//! * `request_*` unpacks the `Demand` object and returns any stored value to the user.
-//!
-//! ## Examples
-//!
-//! ```
-//! # #![feature(provide_any)]
-//! use std::any::{Provider, Demand, request_ref};
-//!
-//! // Definition of MyTrait, a data provider.
-//! trait MyTrait: Provider {
-//!     // ...
-//! }
-//!
-//! // Methods on `MyTrait` trait objects.
-//! impl dyn MyTrait + '_ {
-//!     /// Get a reference to a field of the implementing struct.
-//!     pub fn get_context_by_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
-//!         request_ref::<T>(self)
-//!     }
-//! }
-//!
-//! // Downstream implementation of `MyTrait` and `Provider`.
-//! # struct SomeConcreteType { some_string: String }
-//! impl MyTrait for SomeConcreteType {
-//!     // ...
-//! }
-//!
-//! impl Provider for SomeConcreteType {
-//!     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-//!         // Provide a string reference. We could provide multiple values with
-//!         // different types here.
-//!         demand.provide_ref::<String>(&self.some_string);
-//!     }
-//! }
-//!
-//! // Downstream usage of `MyTrait`.
-//! fn use_my_trait(obj: &dyn MyTrait) {
-//!     // Request a &String from obj.
-//!     let _ = obj.get_context_by_ref::<String>().unwrap();
-//! }
-//! ```
-//!
-//! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then
-//! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -798,524 +732,3 @@ pub const fn type_name<T: ?Sized>() -> &'static str {
 pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
     type_name::<T>()
 }
-
-///////////////////////////////////////////////////////////////////////////////
-// Provider trait
-///////////////////////////////////////////////////////////////////////////////
-
-/// Trait implemented by a type which can dynamically provide values based on type.
-#[unstable(feature = "provide_any", issue = "96024")]
-pub trait Provider {
-    /// Data providers should implement this method to provide *all* values they are able to
-    /// provide by using `demand`.
-    ///
-    /// Note that the `provide_*` methods on `Demand` have short-circuit semantics: if an earlier
-    /// method has successfully provided a value, then later methods will not get an opportunity to
-    /// provide.
-    ///
-    /// # Examples
-    ///
-    /// Provides a reference to a field with type `String` as a `&str`, and a value of
-    /// type `i32`.
-    ///
-    /// ```rust
-    /// # #![feature(provide_any)]
-    /// use std::any::{Provider, Demand};
-    /// # struct SomeConcreteType { field: String, num_field: i32 }
-    ///
-    /// impl Provider for SomeConcreteType {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_ref::<str>(&self.field)
-    ///             .provide_value::<i32>(self.num_field);
-    ///     }
-    /// }
-    /// ```
-    #[unstable(feature = "provide_any", issue = "96024")]
-    fn provide<'a>(&'a self, demand: &mut Demand<'a>);
-}
-
-/// Request a value from the `Provider`.
-///
-/// # Examples
-///
-/// Get a string value from a provider.
-///
-/// ```rust
-/// # #![feature(provide_any)]
-/// use std::any::{Provider, request_value};
-///
-/// fn get_string(provider: &impl Provider) -> String {
-///     request_value::<String>(provider).unwrap()
-/// }
-/// ```
-#[unstable(feature = "provide_any", issue = "96024")]
-pub fn request_value<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<T>
-where
-    T: 'static,
-{
-    request_by_type_tag::<'a, tags::Value<T>>(provider)
-}
-
-/// Request a reference from the `Provider`.
-///
-/// # Examples
-///
-/// Get a string reference from a provider.
-///
-/// ```rust
-/// # #![feature(provide_any)]
-/// use std::any::{Provider, request_ref};
-///
-/// fn get_str(provider: &impl Provider) -> &str {
-///     request_ref::<str>(provider).unwrap()
-/// }
-/// ```
-#[unstable(feature = "provide_any", issue = "96024")]
-pub fn request_ref<'a, T>(provider: &'a (impl Provider + ?Sized)) -> Option<&'a T>
-where
-    T: 'static + ?Sized,
-{
-    request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(provider)
-}
-
-/// Request a specific value by tag from the `Provider`.
-fn request_by_type_tag<'a, I>(provider: &'a (impl Provider + ?Sized)) -> Option<I::Reified>
-where
-    I: tags::Type<'a>,
-{
-    let mut tagged = TaggedOption::<'a, I>(None);
-    provider.provide(tagged.as_demand());
-    tagged.0
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Demand and its methods
-///////////////////////////////////////////////////////////////////////////////
-
-/// A helper object for providing data by type.
-///
-/// A data provider provides values by calling this type's provide methods.
-#[unstable(feature = "provide_any", issue = "96024")]
-#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
-pub struct Demand<'a>(dyn Erased<'a> + 'a);
-
-impl<'a> Demand<'a> {
-    /// Create a new `&mut Demand` from a `&mut dyn Erased` trait object.
-    fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Demand<'a> {
-        // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Demand<'a>` is safe since
-        // `Demand` is repr(transparent).
-        unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Demand<'a>) }
-    }
-
-    /// Provide a value or other type with only static lifetimes.
-    ///
-    /// # Examples
-    ///
-    /// Provides an `u8`.
-    ///
-    /// ```rust
-    /// #![feature(provide_any)]
-    ///
-    /// use std::any::{Provider, Demand};
-    /// # struct SomeConcreteType { field: u8 }
-    ///
-    /// impl Provider for SomeConcreteType {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_value::<u8>(self.field);
-    ///     }
-    /// }
-    /// ```
-    #[unstable(feature = "provide_any", issue = "96024")]
-    pub fn provide_value<T>(&mut self, value: T) -> &mut Self
-    where
-        T: 'static,
-    {
-        self.provide::<tags::Value<T>>(value)
-    }
-
-    /// Provide a value or other type with only static lifetimes computed using a closure.
-    ///
-    /// # Examples
-    ///
-    /// Provides a `String` by cloning.
-    ///
-    /// ```rust
-    /// #![feature(provide_any)]
-    ///
-    /// use std::any::{Provider, Demand};
-    /// # struct SomeConcreteType { field: String }
-    ///
-    /// impl Provider for SomeConcreteType {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_value_with::<String>(|| self.field.clone());
-    ///     }
-    /// }
-    /// ```
-    #[unstable(feature = "provide_any", issue = "96024")]
-    pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
-    where
-        T: 'static,
-    {
-        self.provide_with::<tags::Value<T>>(fulfil)
-    }
-
-    /// Provide a reference. The referee type must be bounded by `'static`,
-    /// but may be unsized.
-    ///
-    /// # Examples
-    ///
-    /// Provides a reference to a field as a `&str`.
-    ///
-    /// ```rust
-    /// #![feature(provide_any)]
-    ///
-    /// use std::any::{Provider, Demand};
-    /// # struct SomeConcreteType { field: String }
-    ///
-    /// impl Provider for SomeConcreteType {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_ref::<str>(&self.field);
-    ///     }
-    /// }
-    /// ```
-    #[unstable(feature = "provide_any", issue = "96024")]
-    pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self {
-        self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
-    }
-
-    /// Provide a reference computed using a closure. The referee type
-    /// must be bounded by `'static`, but may be unsized.
-    ///
-    /// # Examples
-    ///
-    /// Provides a reference to a field as a `&str`.
-    ///
-    /// ```rust
-    /// #![feature(provide_any)]
-    ///
-    /// use std::any::{Provider, Demand};
-    /// # struct SomeConcreteType { business: String, party: String }
-    /// # fn today_is_a_weekday() -> bool { true }
-    ///
-    /// impl Provider for SomeConcreteType {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_ref_with::<str>(|| {
-    ///             if today_is_a_weekday() {
-    ///                 &self.business
-    ///             } else {
-    ///                 &self.party
-    ///             }
-    ///         });
-    ///     }
-    /// }
-    /// ```
-    #[unstable(feature = "provide_any", issue = "96024")]
-    pub fn provide_ref_with<T: ?Sized + 'static>(
-        &mut self,
-        fulfil: impl FnOnce() -> &'a T,
-    ) -> &mut Self {
-        self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil)
-    }
-
-    /// Provide a value with the given `Type` tag.
-    fn provide<I>(&mut self, value: I::Reified) -> &mut Self
-    where
-        I: tags::Type<'a>,
-    {
-        if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() {
-            res.0 = Some(value);
-        }
-        self
-    }
-
-    /// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work.
-    fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self
-    where
-        I: tags::Type<'a>,
-    {
-        if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() {
-            res.0 = Some(fulfil());
-        }
-        self
-    }
-
-    /// Check if the `Demand` would be satisfied if provided with a
-    /// value of the specified type. If the type does not match or has
-    /// already been provided, returns false.
-    ///
-    /// # Examples
-    ///
-    /// Check if an `u8` still needs to be provided and then provides
-    /// it.
-    ///
-    /// ```rust
-    /// #![feature(provide_any)]
-    ///
-    /// use std::any::{Provider, Demand};
-    ///
-    /// struct Parent(Option<u8>);
-    ///
-    /// impl Provider for Parent {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         if let Some(v) = self.0 {
-    ///             demand.provide_value::<u8>(v);
-    ///         }
-    ///     }
-    /// }
-    ///
-    /// struct Child {
-    ///     parent: Parent,
-    /// }
-    ///
-    /// impl Child {
-    ///     // Pretend that this takes a lot of resources to evaluate.
-    ///     fn an_expensive_computation(&self) -> Option<u8> {
-    ///         Some(99)
-    ///     }
-    /// }
-    ///
-    /// impl Provider for Child {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         // In general, we don't know if this call will provide
-    ///         // an `u8` value or not...
-    ///         self.parent.provide(demand);
-    ///
-    ///         // ...so we check to see if the `u8` is needed before
-    ///         // we run our expensive computation.
-    ///         if demand.would_be_satisfied_by_value_of::<u8>() {
-    ///             if let Some(v) = self.an_expensive_computation() {
-    ///                 demand.provide_value::<u8>(v);
-    ///             }
-    ///         }
-    ///
-    ///         // The demand will be satisfied now, regardless of if
-    ///         // the parent provided the value or we did.
-    ///         assert!(!demand.would_be_satisfied_by_value_of::<u8>());
-    ///     }
-    /// }
-    ///
-    /// let parent = Parent(Some(42));
-    /// let child = Child { parent };
-    /// assert_eq!(Some(42), std::any::request_value::<u8>(&child));
-    ///
-    /// let parent = Parent(None);
-    /// let child = Child { parent };
-    /// assert_eq!(Some(99), std::any::request_value::<u8>(&child));
-    /// ```
-    #[unstable(feature = "provide_any", issue = "96024")]
-    pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
-    where
-        T: 'static,
-    {
-        self.would_be_satisfied_by::<tags::Value<T>>()
-    }
-
-    /// Check if the `Demand` would be satisfied if provided with a
-    /// reference to a value of the specified type. If the type does
-    /// not match or has already been provided, returns false.
-    ///
-    /// # Examples
-    ///
-    /// Check if a `&str` still needs to be provided and then provides
-    /// it.
-    ///
-    /// ```rust
-    /// #![feature(provide_any)]
-    ///
-    /// use std::any::{Provider, Demand};
-    ///
-    /// struct Parent(Option<String>);
-    ///
-    /// impl Provider for Parent {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         if let Some(v) = &self.0 {
-    ///             demand.provide_ref::<str>(v);
-    ///         }
-    ///     }
-    /// }
-    ///
-    /// struct Child {
-    ///     parent: Parent,
-    ///     name: String,
-    /// }
-    ///
-    /// impl Child {
-    ///     // Pretend that this takes a lot of resources to evaluate.
-    ///     fn an_expensive_computation(&self) -> Option<&str> {
-    ///         Some(&self.name)
-    ///     }
-    /// }
-    ///
-    /// impl Provider for Child {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         // In general, we don't know if this call will provide
-    ///         // a `str` reference or not...
-    ///         self.parent.provide(demand);
-    ///
-    ///         // ...so we check to see if the `&str` is needed before
-    ///         // we run our expensive computation.
-    ///         if demand.would_be_satisfied_by_ref_of::<str>() {
-    ///             if let Some(v) = self.an_expensive_computation() {
-    ///                 demand.provide_ref::<str>(v);
-    ///             }
-    ///         }
-    ///
-    ///         // The demand will be satisfied now, regardless of if
-    ///         // the parent provided the reference or we did.
-    ///         assert!(!demand.would_be_satisfied_by_ref_of::<str>());
-    ///     }
-    /// }
-    ///
-    /// let parent = Parent(Some("parent".into()));
-    /// let child = Child { parent, name: "child".into() };
-    /// assert_eq!(Some("parent"), std::any::request_ref::<str>(&child));
-    ///
-    /// let parent = Parent(None);
-    /// let child = Child { parent, name: "child".into() };
-    /// assert_eq!(Some("child"), std::any::request_ref::<str>(&child));
-    /// ```
-    #[unstable(feature = "provide_any", issue = "96024")]
-    pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
-    where
-        T: ?Sized + 'static,
-    {
-        self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>()
-    }
-
-    fn would_be_satisfied_by<I>(&self) -> bool
-    where
-        I: tags::Type<'a>,
-    {
-        matches!(self.0.downcast::<I>(), Some(TaggedOption(None)))
-    }
-}
-
-#[unstable(feature = "provide_any", issue = "96024")]
-impl<'a> fmt::Debug for Demand<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Demand").finish_non_exhaustive()
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Type tags
-///////////////////////////////////////////////////////////////////////////////
-
-mod tags {
-    //! Type tags are used to identify a type using a separate value. This module includes type tags
-    //! for some very common types.
-    //!
-    //! Currently type tags are not exposed to the user. But in the future, if you want to use the
-    //! Provider API with more complex types (typically those including lifetime parameters), you
-    //! will need to write your own tags.
-
-    use crate::marker::PhantomData;
-
-    /// This trait is implemented by specific tag types in order to allow
-    /// describing a type which can be requested for a given lifetime `'a`.
-    ///
-    /// A few example implementations for type-driven tags can be found in this
-    /// module, although crates may also implement their own tags for more
-    /// complex types with internal lifetimes.
-    pub trait Type<'a>: Sized + 'static {
-        /// The type of values which may be tagged by this tag for the given
-        /// lifetime.
-        type Reified: 'a;
-    }
-
-    /// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a
-    /// `?Sized` bound). E.g., `str`.
-    pub trait MaybeSizedType<'a>: Sized + 'static {
-        type Reified: 'a + ?Sized;
-    }
-
-    impl<'a, T: Type<'a>> MaybeSizedType<'a> for T {
-        type Reified = T::Reified;
-    }
-
-    /// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements.
-    #[derive(Debug)]
-    pub struct Value<T: 'static>(PhantomData<T>);
-
-    impl<'a, T: 'static> Type<'a> for Value<T> {
-        type Reified = T;
-    }
-
-    /// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound).
-    #[derive(Debug)]
-    pub struct MaybeSizedValue<T: ?Sized + 'static>(PhantomData<T>);
-
-    impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue<T> {
-        type Reified = T;
-    }
-
-    /// Type-based tag for reference types (`&'a T`, where T is represented by
-    /// `<I as MaybeSizedType<'a>>::Reified`.
-    #[derive(Debug)]
-    pub struct Ref<I>(PhantomData<I>);
-
-    impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref<I> {
-        type Reified = &'a I::Reified;
-    }
-}
-
-/// An `Option` with a type tag `I`.
-///
-/// Since this struct implements `Erased`, the type can be erased to make a dynamically typed
-/// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically
-/// checked for the concrete type, there is some degree of type safety.
-#[repr(transparent)]
-struct TaggedOption<'a, I: tags::Type<'a>>(Option<I::Reified>);
-
-impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> {
-    fn as_demand(&mut self) -> &mut Demand<'a> {
-        Demand::new(self as &mut (dyn Erased<'a> + 'a))
-    }
-}
-
-/// Represents a type-erased but identifiable object.
-///
-/// This trait is exclusively implemented by the `TaggedOption` type.
-unsafe trait Erased<'a>: 'a {
-    /// The `TypeId` of the erased type.
-    fn tag_id(&self) -> TypeId;
-}
-
-unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {
-    fn tag_id(&self) -> TypeId {
-        TypeId::of::<I>()
-    }
-}
-
-#[unstable(feature = "provide_any", issue = "96024")]
-impl<'a> dyn Erased<'a> + 'a {
-    /// Returns some reference to the dynamic value if it is tagged with `I`,
-    /// or `None` otherwise.
-    #[inline]
-    fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>>
-    where
-        I: tags::Type<'a>,
-    {
-        if self.tag_id() == TypeId::of::<I>() {
-            // SAFETY: Just checked whether we're pointing to an I.
-            Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() })
-        } else {
-            None
-        }
-    }
-
-    /// Returns some mutable reference to the dynamic value if it is tagged with `I`,
-    /// or `None` otherwise.
-    #[inline]
-    fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>>
-    where
-        I: tags::Type<'a>,
-    {
-        if self.tag_id() == TypeId::of::<I>() {
-            // SAFETY: Just checked whether we're pointing to an I.
-            Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() })
-        } else {
-            None
-        }
-    }
-}
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 11cb0827578..c32a54b77ef 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -4,8 +4,8 @@
 #[cfg(test)]
 mod tests;
 
-use crate::any::{Demand, Provider, TypeId};
-use crate::fmt::{Debug, Display};
+use crate::any::TypeId;
+use crate::fmt::{Debug, Display, Formatter, Result};
 
 /// `Error` is a trait representing the basic expectations for error values,
 /// i.e., values of type `E` in [`Result<T, E>`].
@@ -123,16 +123,20 @@ pub trait Error: Debug + Display {
 
     /// Provides type based access to context intended for error reports.
     ///
-    /// Used in conjunction with [`Demand::provide_value`] and [`Demand::provide_ref`] to extract
+    /// Used in conjunction with [`Request::provide_value`] and [`Request::provide_ref`] to extract
     /// references to member variables from `dyn Error` trait objects.
     ///
     /// # Example
     ///
     /// ```rust
-    /// #![feature(provide_any)]
     /// #![feature(error_generic_member_access)]
     /// use core::fmt;
-    /// use core::any::Demand;
+    /// use core::error::{request_ref, Request};
+    ///
+    /// #[derive(Debug)]
+    /// enum MyLittleTeaPot {
+    ///     Empty,
+    /// }
     ///
     /// #[derive(Debug)]
     /// struct MyBacktrace {
@@ -147,21 +151,7 @@ pub trait Error: Debug + Display {
     /// }
     ///
     /// #[derive(Debug)]
-    /// struct SourceError {
-    ///     // ...
-    /// }
-    ///
-    /// impl fmt::Display for SourceError {
-    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f, "Example Source Error")
-    ///     }
-    /// }
-    ///
-    /// impl std::error::Error for SourceError {}
-    ///
-    /// #[derive(Debug)]
     /// struct Error {
-    ///     source: SourceError,
     ///     backtrace: MyBacktrace,
     /// }
     ///
@@ -172,38 +162,26 @@ pub trait Error: Debug + Display {
     /// }
     ///
     /// impl std::error::Error for Error {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand
-    ///             .provide_ref::<MyBacktrace>(&self.backtrace)
-    ///             .provide_ref::<dyn std::error::Error + 'static>(&self.source);
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         request
+    ///             .provide_ref::<MyBacktrace>(&self.backtrace);
     ///     }
     /// }
     ///
     /// fn main() {
     ///     let backtrace = MyBacktrace::new();
-    ///     let source = SourceError {};
-    ///     let error = Error { source, backtrace };
+    ///     let error = Error { backtrace };
     ///     let dyn_error = &error as &dyn std::error::Error;
-    ///     let backtrace_ref = dyn_error.request_ref::<MyBacktrace>().unwrap();
+    ///     let backtrace_ref = request_ref::<MyBacktrace>(dyn_error).unwrap();
     ///
     ///     assert!(core::ptr::eq(&error.backtrace, backtrace_ref));
+    ///     assert!(request_ref::<MyLittleTeaPot>(dyn_error).is_none());
     /// }
     /// ```
     #[unstable(feature = "error_generic_member_access", issue = "99301")]
     #[allow(unused_variables)]
-    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {}
-}
-
-#[unstable(feature = "error_generic_member_access", issue = "99301")]
-impl<E> Provider for E
-where
-    E: Error + ?Sized,
-{
-    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-        self.provide(demand)
-    }
+    fn provide<'a>(&'a self, request: &mut Request<'a>) {}
 }
-
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
     // implementations, since that can enable unsound downcasting.
@@ -215,20 +193,6 @@ mod private {
 #[unstable(feature = "never_type", issue = "35121")]
 impl Error for ! {}
 
-impl<'a> dyn Error + 'a {
-    /// Request a reference of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_ref<T: ?Sized + 'static>(&'a self) -> Option<&'a T> {
-        core::any::request_ref(self)
-    }
-
-    /// Request a value of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_value<T: 'static>(&'a self) -> Option<T> {
-        core::any::request_value(self)
-    }
-}
-
 // Copied from `any.rs`.
 impl dyn Error + 'static {
     /// Returns `true` if the inner type is the same as `T`.
@@ -293,18 +257,6 @@ impl dyn Error + 'static + Send {
     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
         <dyn Error + 'static>::downcast_mut::<T>(self)
     }
-
-    /// Request a reference of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
-        <dyn Error>::request_ref(self)
-    }
-
-    /// Request a value of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_value<T: 'static>(&self) -> Option<T> {
-        <dyn Error>::request_value(self)
-    }
 }
 
 impl dyn Error + 'static + Send + Sync {
@@ -328,18 +280,6 @@ impl dyn Error + 'static + Send + Sync {
     pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
         <dyn Error + 'static>::downcast_mut::<T>(self)
     }
-
-    /// Request a reference of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
-        <dyn Error>::request_ref(self)
-    }
-
-    /// Request a value of type `T` as context about this error.
-    #[unstable(feature = "error_generic_member_access", issue = "99301")]
-    pub fn request_value<T: 'static>(&self) -> Option<T> {
-        <dyn Error>::request_value(self)
-    }
 }
 
 impl dyn Error {
@@ -412,6 +352,645 @@ impl dyn Error {
     }
 }
 
+/// Request a value of type `T` from the given `impl Error`.
+///
+/// # Examples
+///
+/// Get a string value from an error.
+///
+/// ```rust
+/// # #![feature(error_generic_member_access)]
+/// use std::error::Error;
+/// use core::error::request_value;
+///
+/// fn get_string(err: &impl Error) -> String {
+///     request_value::<String>(err).unwrap()
+/// }
+/// ```
+#[unstable(feature = "error_generic_member_access", issue = "99301")]
+pub fn request_value<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<T>
+where
+    T: 'static,
+{
+    request_by_type_tag::<'a, tags::Value<T>>(err)
+}
+
+/// Request a reference of type `T` from the given `impl Error`.
+///
+/// # Examples
+///
+/// Get a string reference from an error.
+///
+/// ```rust
+/// # #![feature(error_generic_member_access)]
+/// use core::error::Error;
+/// use core::error::request_ref;
+///
+/// fn get_str(err: &impl Error) -> &str {
+///     request_ref::<str>(err).unwrap()
+/// }
+/// ```
+#[unstable(feature = "error_generic_member_access", issue = "99301")]
+pub fn request_ref<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<&'a T>
+where
+    T: 'static + ?Sized,
+{
+    request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(err)
+}
+
+/// Request a specific value by tag from the `Error`.
+fn request_by_type_tag<'a, I>(err: &'a (impl Error + ?Sized)) -> Option<I::Reified>
+where
+    I: tags::Type<'a>,
+{
+    let mut tagged = TaggedOption::<'a, I>(None);
+    err.provide(tagged.as_request());
+    tagged.0
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Request and its methods
+///////////////////////////////////////////////////////////////////////////////
+
+/// `Request` supports generic, type-driven access to data. It's use is currently restricted to the
+/// standard library in cases where trait authors wish to allow trait implementors to share generic
+/// information across trait boundaries. The motivating and prototypical use case is
+/// `core::error::Error` which would otherwise require a method per concrete type (eg.
+/// `std::backtrace::Backtrace` instance that implementors want to expose to users).
+///
+/// # Data flow
+///
+/// To describe the intended data flow for Request objects, let's consider two conceptual users
+/// separated by API boundaries:
+///
+/// * Consumer - the consumer requests objects using a Request instance; eg a crate that offers
+/// fancy `Error`/`Result` reporting to users wants to request a Backtrace from a given `dyn Error`.
+///
+/// * Producer - the producer provides objects when requested via Request; eg. a library with an
+/// an `Error` implementation that automatically captures backtraces at the time instances are
+/// created.
+///
+/// The consumer only needs to know where to submit their request and are expected to handle the
+/// request not being fulfilled by the use of `Option<T>` in the responses offered by the producer.
+///
+/// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise
+/// prepared to generate a value requested). eg, `backtrace::Backtrace` or
+/// `std::backtrace::Backtrace`
+/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace). In the case
+/// of a `dyn Error` trait object (the Producer), there are methods called `request_ref` and
+/// `request_value` are available to simplify obtaining an ``Option<T>`` for a given type. * The
+/// Producer, when requested, populates the given Request object which is given as a mutable
+/// reference.
+/// * The Consumer extracts a value or reference to the requested type from the `Request` object
+/// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and `
+/// request_value` methods mean that `dyn Error` users don't have to deal with the `Request` type at
+/// all (but `Error` implementors do). The `None` case of the `Option` suggests only that the
+/// Producer cannot currently offer an instance of the requested type, not it can't or never will.
+///
+/// # Examples
+///
+/// The best way to demonstrate this is using an example implementation of `Error`'s `provide` trait
+/// method:
+///
+/// ```
+/// #![feature(error_generic_member_access)]
+/// use core::fmt;
+/// use core::error::Request;
+/// use core::error::request_ref;
+///
+/// #[derive(Debug)]
+/// enum MyLittleTeaPot {
+///     Empty,
+/// }
+///
+/// #[derive(Debug)]
+/// struct MyBacktrace {
+///     // ...
+/// }
+///
+/// impl MyBacktrace {
+///     fn new() -> MyBacktrace {
+///         // ...
+///         # MyBacktrace {}
+///     }
+/// }
+///
+/// #[derive(Debug)]
+/// struct Error {
+///     backtrace: MyBacktrace,
+/// }
+///
+/// impl fmt::Display for Error {
+///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+///         write!(f, "Example Error")
+///     }
+/// }
+///
+/// impl std::error::Error for Error {
+///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+///         request
+///             .provide_ref::<MyBacktrace>(&self.backtrace);
+///     }
+/// }
+///
+/// fn main() {
+///     let backtrace = MyBacktrace::new();
+///     let error = Error { backtrace };
+///     let dyn_error = &error as &dyn std::error::Error;
+///     let backtrace_ref = request_ref::<MyBacktrace>(dyn_error).unwrap();
+///
+///     assert!(core::ptr::eq(&error.backtrace, backtrace_ref));
+///     assert!(request_ref::<MyLittleTeaPot>(dyn_error).is_none());
+/// }
+/// ```
+///
+#[unstable(feature = "error_generic_member_access", issue = "99301")]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
+pub struct Request<'a>(dyn Erased<'a> + 'a);
+
+impl<'a> Request<'a> {
+    /// Create a new `&mut Request` from a `&mut dyn Erased` trait object.
+    fn new<'b>(erased: &'b mut (dyn Erased<'a> + 'a)) -> &'b mut Request<'a> {
+        // SAFETY: transmuting `&mut (dyn Erased<'a> + 'a)` to `&mut Request<'a>` is safe since
+        // `Request` is repr(transparent).
+        unsafe { &mut *(erased as *mut dyn Erased<'a> as *mut Request<'a>) }
+    }
+
+    /// Provide a value or other type with only static lifetimes.
+    ///
+    /// # Examples
+    ///
+    /// Provides an `u8`.
+    ///
+    /// ```rust
+    /// #![feature(error_generic_member_access)]
+    ///
+    /// use core::error::Request;
+    ///
+    /// #[derive(Debug)]
+    /// struct SomeConcreteType { field: u8 }
+    ///
+    /// impl std::fmt::Display for SomeConcreteType {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "{} failed", self.field)
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for SomeConcreteType {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         request.provide_value::<u8>(self.field);
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn provide_value<T>(&mut self, value: T) -> &mut Self
+    where
+        T: 'static,
+    {
+        self.provide::<tags::Value<T>>(value)
+    }
+
+    /// Provide a value or other type with only static lifetimes computed using a closure.
+    ///
+    /// # Examples
+    ///
+    /// Provides a `String` by cloning.
+    ///
+    /// ```rust
+    /// #![feature(error_generic_member_access)]
+    ///
+    /// use core::error::Request;
+    ///
+    /// #[derive(Debug)]
+    /// struct SomeConcreteType { field: String }
+    ///
+    /// impl std::fmt::Display for SomeConcreteType {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "{} failed", self.field)
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for SomeConcreteType {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         request.provide_value_with::<String>(|| self.field.clone());
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
+    where
+        T: 'static,
+    {
+        self.provide_with::<tags::Value<T>>(fulfil)
+    }
+
+    /// Provide a reference. The referee type must be bounded by `'static`,
+    /// but may be unsized.
+    ///
+    /// # Examples
+    ///
+    /// Provides a reference to a field as a `&str`.
+    ///
+    /// ```rust
+    /// #![feature(error_generic_member_access)]
+    ///
+    /// use core::error::Request;
+    ///
+    /// #[derive(Debug)]
+    /// struct SomeConcreteType { field: String }
+    ///
+    /// impl std::fmt::Display for SomeConcreteType {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "{} failed", self.field)
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for SomeConcreteType {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         request.provide_ref::<str>(&self.field);
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self {
+        self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
+    }
+
+    /// Provide a reference computed using a closure. The referee type
+    /// must be bounded by `'static`, but may be unsized.
+    ///
+    /// # Examples
+    ///
+    /// Provides a reference to a field as a `&str`.
+    ///
+    /// ```rust
+    /// #![feature(error_generic_member_access)]
+    ///
+    /// use core::error::Request;
+    ///
+    /// #[derive(Debug)]
+    /// struct SomeConcreteType { business: String, party: String }
+    /// fn today_is_a_weekday() -> bool { true }
+    ///
+    /// impl std::fmt::Display for SomeConcreteType {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "{} failed", self.business)
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for SomeConcreteType {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         request.provide_ref_with::<str>(|| {
+    ///             if today_is_a_weekday() {
+    ///                 &self.business
+    ///             } else {
+    ///                 &self.party
+    ///             }
+    ///         });
+    ///     }
+    /// }
+    /// ```
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn provide_ref_with<T: ?Sized + 'static>(
+        &mut self,
+        fulfil: impl FnOnce() -> &'a T,
+    ) -> &mut Self {
+        self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil)
+    }
+
+    /// Provide a value with the given `Type` tag.
+    fn provide<I>(&mut self, value: I::Reified) -> &mut Self
+    where
+        I: tags::Type<'a>,
+    {
+        if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() {
+            res.0 = Some(value);
+        }
+        self
+    }
+
+    /// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work.
+    fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self
+    where
+        I: tags::Type<'a>,
+    {
+        if let Some(res @ TaggedOption(None)) = self.0.downcast_mut::<I>() {
+            res.0 = Some(fulfil());
+        }
+        self
+    }
+
+    /// Check if the `Request` would be satisfied if provided with a
+    /// value of the specified type. If the type does not match or has
+    /// already been provided, returns false.
+    ///
+    /// # Examples
+    ///
+    /// Check if an `u8` still needs to be provided and then provides
+    /// it.
+    ///
+    /// ```rust
+    /// #![feature(error_generic_member_access)]
+    ///
+    /// use core::error::Request;
+    /// use core::error::request_value;
+    ///
+    /// #[derive(Debug)]
+    /// struct Parent(Option<u8>);
+    ///
+    /// impl std::fmt::Display for Parent {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "a parent failed")
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for Parent {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         if let Some(v) = self.0 {
+    ///             request.provide_value::<u8>(v);
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// #[derive(Debug)]
+    /// struct Child {
+    ///     parent: Parent,
+    /// }
+    ///
+    /// impl Child {
+    ///     // Pretend that this takes a lot of resources to evaluate.
+    ///     fn an_expensive_computation(&self) -> Option<u8> {
+    ///         Some(99)
+    ///     }
+    /// }
+    ///
+    /// impl std::fmt::Display for Child {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "child failed: \n  because of parent: {}", self.parent)
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for Child {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         // In general, we don't know if this call will provide
+    ///         // an `u8` value or not...
+    ///         self.parent.provide(request);
+    ///
+    ///         // ...so we check to see if the `u8` is needed before
+    ///         // we run our expensive computation.
+    ///         if request.would_be_satisfied_by_value_of::<u8>() {
+    ///             if let Some(v) = self.an_expensive_computation() {
+    ///                 request.provide_value::<u8>(v);
+    ///             }
+    ///         }
+    ///
+    ///         // The request will be satisfied now, regardless of if
+    ///         // the parent provided the value or we did.
+    ///         assert!(!request.would_be_satisfied_by_value_of::<u8>());
+    ///     }
+    /// }
+    ///
+    /// let parent = Parent(Some(42));
+    /// let child = Child { parent };
+    /// assert_eq!(Some(42), request_value::<u8>(&child));
+    ///
+    /// let parent = Parent(None);
+    /// let child = Child { parent };
+    /// assert_eq!(Some(99), request_value::<u8>(&child));
+    ///
+    /// ```
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
+    where
+        T: 'static,
+    {
+        self.would_be_satisfied_by::<tags::Value<T>>()
+    }
+
+    /// Check if the `Request` would be satisfied if provided with a
+    /// reference to a value of the specified type. If the type does
+    /// not match or has already been provided, returns false.
+    ///
+    /// # Examples
+    ///
+    /// Check if a `&str` still needs to be provided and then provides
+    /// it.
+    ///
+    /// ```rust
+    /// #![feature(error_generic_member_access)]
+    ///
+    /// use core::error::Request;
+    /// use core::error::request_ref;
+    ///
+    /// #[derive(Debug)]
+    /// struct Parent(Option<String>);
+    ///
+    /// impl std::fmt::Display for Parent {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "a parent failed")
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for Parent {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         if let Some(v) = &self.0 {
+    ///             request.provide_ref::<str>(v);
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// #[derive(Debug)]
+    /// struct Child {
+    ///     parent: Parent,
+    ///     name: String,
+    /// }
+    ///
+    /// impl Child {
+    ///     // Pretend that this takes a lot of resources to evaluate.
+    ///     fn an_expensive_computation(&self) -> Option<&str> {
+    ///         Some(&self.name)
+    ///     }
+    /// }
+    ///
+    /// impl std::fmt::Display for Child {
+    ///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+    ///         write!(f, "{} failed: \n  {}", self.name, self.parent)
+    ///     }
+    /// }
+    ///
+    /// impl std::error::Error for Child {
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         // In general, we don't know if this call will provide
+    ///         // a `str` reference or not...
+    ///         self.parent.provide(request);
+    ///
+    ///         // ...so we check to see if the `&str` is needed before
+    ///         // we run our expensive computation.
+    ///         if request.would_be_satisfied_by_ref_of::<str>() {
+    ///             if let Some(v) = self.an_expensive_computation() {
+    ///                 request.provide_ref::<str>(v);
+    ///             }
+    ///         }
+    ///
+    ///         // The request will be satisfied now, regardless of if
+    ///         // the parent provided the reference or we did.
+    ///         assert!(!request.would_be_satisfied_by_ref_of::<str>());
+    ///     }
+    /// }
+    ///
+    /// let parent = Parent(Some("parent".into()));
+    /// let child = Child { parent, name: "child".into() };
+    /// assert_eq!(Some("parent"), request_ref::<str>(&child));
+    ///
+    /// let parent = Parent(None);
+    /// let child = Child { parent, name: "child".into() };
+    /// assert_eq!(Some("child"), request_ref::<str>(&child));
+    /// ```
+    #[unstable(feature = "error_generic_member_access", issue = "99301")]
+    pub fn would_be_satisfied_by_ref_of<T>(&self) -> bool
+    where
+        T: ?Sized + 'static,
+    {
+        self.would_be_satisfied_by::<tags::Ref<tags::MaybeSizedValue<T>>>()
+    }
+
+    fn would_be_satisfied_by<I>(&self) -> bool
+    where
+        I: tags::Type<'a>,
+    {
+        matches!(self.0.downcast::<I>(), Some(TaggedOption(None)))
+    }
+}
+
+#[unstable(feature = "error_generic_member_access", issue = "99301")]
+impl<'a> Debug for Request<'a> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+        f.debug_struct("Request").finish_non_exhaustive()
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Type tags
+///////////////////////////////////////////////////////////////////////////////
+
+pub(crate) mod tags {
+    //! Type tags are used to identify a type using a separate value. This module includes type tags
+    //! for some very common types.
+    //!
+    //! Currently type tags are not exposed to the user. But in the future, if you want to use the
+    //! Request API with more complex types (typically those including lifetime parameters), you
+    //! will need to write your own tags.
+
+    use crate::marker::PhantomData;
+
+    /// This trait is implemented by specific tag types in order to allow
+    /// describing a type which can be requested for a given lifetime `'a`.
+    ///
+    /// A few example implementations for type-driven tags can be found in this
+    /// module, although crates may also implement their own tags for more
+    /// complex types with internal lifetimes.
+    pub(crate) trait Type<'a>: Sized + 'static {
+        /// The type of values which may be tagged by this tag for the given
+        /// lifetime.
+        type Reified: 'a;
+    }
+
+    /// Similar to the [`Type`] trait, but represents a type which may be unsized (i.e., has a
+    /// `?Sized` bound). E.g., `str`.
+    pub(crate) trait MaybeSizedType<'a>: Sized + 'static {
+        type Reified: 'a + ?Sized;
+    }
+
+    impl<'a, T: Type<'a>> MaybeSizedType<'a> for T {
+        type Reified = T::Reified;
+    }
+
+    /// Type-based tag for types bounded by `'static`, i.e., with no borrowed elements.
+    #[derive(Debug)]
+    pub(crate) struct Value<T: 'static>(PhantomData<T>);
+
+    impl<'a, T: 'static> Type<'a> for Value<T> {
+        type Reified = T;
+    }
+
+    /// Type-based tag similar to [`Value`] but which may be unsized (i.e., has a `?Sized` bound).
+    #[derive(Debug)]
+    pub(crate) struct MaybeSizedValue<T: ?Sized + 'static>(PhantomData<T>);
+
+    impl<'a, T: ?Sized + 'static> MaybeSizedType<'a> for MaybeSizedValue<T> {
+        type Reified = T;
+    }
+
+    /// Type-based tag for reference types (`&'a T`, where T is represented by
+    /// `<I as MaybeSizedType<'a>>::Reified`.
+    #[derive(Debug)]
+    pub(crate) struct Ref<I>(PhantomData<I>);
+
+    impl<'a, I: MaybeSizedType<'a>> Type<'a> for Ref<I> {
+        type Reified = &'a I::Reified;
+    }
+}
+
+/// An `Option` with a type tag `I`.
+///
+/// Since this struct implements `Erased`, the type can be erased to make a dynamically typed
+/// option. The type can be checked dynamically using `Erased::tag_id` and since this is statically
+/// checked for the concrete type, there is some degree of type safety.
+#[repr(transparent)]
+pub(crate) struct TaggedOption<'a, I: tags::Type<'a>>(pub Option<I::Reified>);
+
+impl<'a, I: tags::Type<'a>> TaggedOption<'a, I> {
+    pub(crate) fn as_request(&mut self) -> &mut Request<'a> {
+        Request::new(self as &mut (dyn Erased<'a> + 'a))
+    }
+}
+
+/// Represents a type-erased but identifiable object.
+///
+/// This trait is exclusively implemented by the `TaggedOption` type.
+unsafe trait Erased<'a>: 'a {
+    /// The `TypeId` of the erased type.
+    fn tag_id(&self) -> TypeId;
+}
+
+unsafe impl<'a, I: tags::Type<'a>> Erased<'a> for TaggedOption<'a, I> {
+    fn tag_id(&self) -> TypeId {
+        TypeId::of::<I>()
+    }
+}
+
+impl<'a> dyn Erased<'a> + 'a {
+    /// Returns some reference to the dynamic value if it is tagged with `I`,
+    /// or `None` otherwise.
+    #[inline]
+    fn downcast<I>(&self) -> Option<&TaggedOption<'a, I>>
+    where
+        I: tags::Type<'a>,
+    {
+        if self.tag_id() == TypeId::of::<I>() {
+            // SAFETY: Just checked whether we're pointing to an I.
+            Some(unsafe { &*(self as *const Self).cast::<TaggedOption<'a, I>>() })
+        } else {
+            None
+        }
+    }
+
+    /// Returns some mutable reference to the dynamic value if it is tagged with `I`,
+    /// or `None` otherwise.
+    #[inline]
+    fn downcast_mut<I>(&mut self) -> Option<&mut TaggedOption<'a, I>>
+    where
+        I: tags::Type<'a>,
+    {
+        if self.tag_id() == TypeId::of::<I>() {
+            // SAFETY: Just checked whether we're pointing to an I.
+            Some(unsafe { &mut *(self as *mut Self).cast::<TaggedOption<'a, I>>() })
+        } else {
+            None
+        }
+    }
+}
+
 /// An iterator over an [`Error`] and its sources.
 ///
 /// If you want to omit the initial error and only process
@@ -449,8 +1028,8 @@ impl<'a, T: Error + ?Sized> Error for &'a T {
         Error::source(&**self)
     }
 
-    fn provide<'b>(&'b self, demand: &mut Demand<'b>) {
-        Error::provide(&**self, demand);
+    fn provide<'b>(&'b self, request: &mut Request<'b>) {
+        Error::provide(&**self, request);
     }
 }
 
diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs
index a8f6b7ebb92..8d2d31b6431 100644
--- a/library/core/tests/any.rs
+++ b/library/core/tests/any.rs
@@ -147,65 +147,3 @@ fn dyn_type_name() {
         std::any::type_name::<dyn Foo<Bar = i32> + Send + Sync>()
     );
 }
-
-// Test the `Provider` API.
-
-struct SomeConcreteType {
-    some_string: String,
-}
-
-impl Provider for SomeConcreteType {
-    fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-        demand
-            .provide_ref::<String>(&self.some_string)
-            .provide_ref::<str>(&self.some_string)
-            .provide_value_with::<String>(|| "bye".to_owned());
-    }
-}
-
-// Test the provide and request mechanisms with a by-reference trait object.
-#[test]
-fn test_provider() {
-    let obj: &dyn Provider = &SomeConcreteType { some_string: "hello".to_owned() };
-
-    assert_eq!(&**request_ref::<String>(obj).unwrap(), "hello");
-    assert_eq!(&*request_value::<String>(obj).unwrap(), "bye");
-    assert_eq!(request_value::<u8>(obj), None);
-}
-
-// Test the provide and request mechanisms with a boxed trait object.
-#[test]
-fn test_provider_boxed() {
-    let obj: Box<dyn Provider> = Box::new(SomeConcreteType { some_string: "hello".to_owned() });
-
-    assert_eq!(&**request_ref::<String>(&*obj).unwrap(), "hello");
-    assert_eq!(&*request_value::<String>(&*obj).unwrap(), "bye");
-    assert_eq!(request_value::<u8>(&*obj), None);
-}
-
-// Test the provide and request mechanisms with a concrete object.
-#[test]
-fn test_provider_concrete() {
-    let obj = SomeConcreteType { some_string: "hello".to_owned() };
-
-    assert_eq!(&**request_ref::<String>(&obj).unwrap(), "hello");
-    assert_eq!(&*request_value::<String>(&obj).unwrap(), "bye");
-    assert_eq!(request_value::<u8>(&obj), None);
-}
-
-trait OtherTrait: Provider {}
-
-impl OtherTrait for SomeConcreteType {}
-
-impl dyn OtherTrait {
-    fn get_ref<T: 'static + ?Sized>(&self) -> Option<&T> {
-        request_ref::<T>(self)
-    }
-}
-
-// Test the provide and request mechanisms via an intermediate trait.
-#[test]
-fn test_provider_intermediate() {
-    let obj: &dyn OtherTrait = &SomeConcreteType { some_string: "hello".to_owned() };
-    assert_eq!(obj.get_ref::<str>().unwrap(), "hello");
-}
diff --git a/library/core/tests/error.rs b/library/core/tests/error.rs
new file mode 100644
index 00000000000..cb7cb5441d1
--- /dev/null
+++ b/library/core/tests/error.rs
@@ -0,0 +1,66 @@
+use core::error::{request_value, request_ref, Request};
+
+// Test the `Request` API.
+#[derive(Debug)]
+struct SomeConcreteType {
+    some_string: String,
+}
+
+impl std::fmt::Display for SomeConcreteType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "A")
+    }
+}
+
+impl std::error::Error for SomeConcreteType {
+    fn provide<'a>(&'a self, request: &mut Request<'a>) {
+        request
+            .provide_ref::<String>(&self.some_string)
+            .provide_ref::<str>(&self.some_string)
+            .provide_value_with::<String>(|| "bye".to_owned());
+    }
+}
+
+// Test the Error.provide and request mechanisms with a by-reference trait object.
+#[test]
+fn test_error_generic_member_access() {
+    let obj = &SomeConcreteType { some_string: "hello".to_owned() };
+
+    assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello");
+    assert_eq!(request_value::<String>(&*obj).unwrap(), "bye");
+    assert_eq!(request_value::<u8>(&obj), None);
+}
+
+// Test the Error.provide and request mechanisms with a by-reference trait object.
+#[test]
+fn test_request_constructor() {
+    let obj: &dyn std::error::Error = &SomeConcreteType { some_string: "hello".to_owned() };
+
+    assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello");
+    assert_eq!(request_value::<String>(&*obj).unwrap(), "bye");
+    assert_eq!(request_value::<u8>(&obj), None);
+}
+
+// Test the Error.provide and request mechanisms with a boxed trait object.
+#[test]
+fn test_error_generic_member_access_boxed() {
+    let obj: Box<dyn std::error::Error> =
+        Box::new(SomeConcreteType { some_string: "hello".to_owned() });
+
+    assert_eq!(request_ref::<String>(&*obj).unwrap(), "hello");
+    assert_eq!(request_value::<String>(&*obj).unwrap(), "bye");
+
+    // NOTE: Box<E> only implements Error when E: Error + Sized, which means we can't pass a
+    // Box<dyn Error> to request_value.
+    //assert_eq!(request_value::<String>(&obj).unwrap(), "bye");
+}
+
+// Test the Error.provide and request mechanisms with a concrete object.
+#[test]
+fn test_error_generic_member_access_concrete() {
+    let obj = SomeConcreteType { some_string: "hello".to_owned() };
+
+    assert_eq!(request_ref::<String>(&obj).unwrap(), "hello");
+    assert_eq!(request_value::<String>(&obj).unwrap(), "bye");
+    assert_eq!(request_value::<u8>(&obj), None);
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 897a5e9b870..e5517991682 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -105,7 +105,9 @@
 #![feature(const_slice_from_ref)]
 #![feature(waker_getters)]
 #![feature(slice_flatten)]
-#![feature(provide_any)]
+#![feature(error_generic_member_access)]
+#![feature(error_in_core)]
+#![feature(trait_upcasting)]
 #![feature(utf8_chunks)]
 #![feature(is_ascii_octdigit)]
 #![feature(get_many_mut)]
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index ee5eddebfaf..7bc3af1793e 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -9,6 +9,8 @@ use crate::fmt::{self, Write};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::error::Error;
+#[unstable(feature = "error_generic_member_access", issue = "99301")]
+pub use core::error::{request_ref, Request};
 
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
@@ -371,11 +373,10 @@ impl<E> Report<E> {
     ///
     /// ```rust
     /// #![feature(error_reporter)]
-    /// #![feature(provide_any)]
     /// #![feature(error_generic_member_access)]
     /// # use std::error::Error;
     /// # use std::fmt;
-    /// use std::any::Demand;
+    /// use std::error::Request;
     /// use std::error::Report;
     /// use std::backtrace::Backtrace;
     ///
@@ -405,8 +406,8 @@ impl<E> Report<E> {
     /// }
     ///
     /// impl Error for SuperErrorSideKick {
-    ///     fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
-    ///         demand.provide_ref::<Backtrace>(&self.backtrace);
+    ///     fn provide<'a>(&'a self, request: &mut Request<'a>) {
+    ///         request.provide_ref::<Backtrace>(&self.backtrace);
     ///     }
     /// }
     ///
@@ -459,11 +460,11 @@ where
     fn backtrace(&self) -> Option<&Backtrace> {
         // have to grab the backtrace on the first error directly since that error may not be
         // 'static
-        let backtrace = (&self.error as &dyn Error).request_ref();
+        let backtrace = request_ref(&self.error);
         let backtrace = backtrace.or_else(|| {
             self.error
                 .source()
-                .map(|source| source.sources().find_map(|source| source.request_ref()))
+                .map(|source| source.sources().find_map(|source| request_ref(source)))
                 .flatten()
         });
         backtrace
diff --git a/library/std/src/error/tests.rs b/library/std/src/error/tests.rs
index ee999bd65c3..ed070a26b0c 100644
--- a/library/std/src/error/tests.rs
+++ b/library/std/src/error/tests.rs
@@ -1,6 +1,6 @@
 use super::Error;
 use crate::fmt;
-use core::any::Demand;
+use core::error::Request;
 
 #[derive(Debug, PartialEq)]
 struct A;
@@ -199,7 +199,7 @@ where
         self.source.as_deref()
     }
 
-    fn provide<'a>(&'a self, req: &mut Demand<'a>) {
+    fn provide<'a>(&'a self, req: &mut Request<'a>) {
         self.backtrace.as_ref().map(|bt| req.provide_ref::<Backtrace>(bt));
     }
 }
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 6f58e5a0f05..c07aa5cd91f 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -306,7 +306,6 @@
 #![feature(pointer_is_aligned)]
 #![feature(portable_simd)]
 #![feature(prelude_2024)]
-#![feature(provide_any)]
 #![feature(ptr_as_uninit)]
 #![feature(raw_os_nonzero)]
 #![feature(round_ties_even)]