summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-07-14 19:24:02 +0530
committerGitHub <noreply@github.com>2022-07-14 19:24:02 +0530
commit2b17aa67fc91b233bcca7ee91d55ee37706b01c7 (patch)
tree21cec7a609c8942ffc0770c68c500f21999a896b /library/std/src
parentf1a8854f9be2e5cad764d630a53d26c7b72f8162 (diff)
parent655d6e82e3f89e1c26c4519134013f335d8880eb (diff)
downloadrust-2b17aa67fc91b233bcca7ee91d55ee37706b01c7.tar.gz
rust-2b17aa67fc91b233bcca7ee91d55ee37706b01c7.zip
Rollup merge of #98072 - yaahc:generic-member-access, r=thomcc
Add provider API to error trait

Implements https://github.com/rust-lang/rfcs/pull/2895
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/error.rs117
-rw-r--r--library/std/src/lib.rs1
2 files changed, 117 insertions, 1 deletions
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 87f213b1608..57f16f9517f 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -156,7 +156,7 @@ use core::array;
 use core::convert::Infallible;
 
 use crate::alloc::{AllocError, LayoutError};
-use crate::any::TypeId;
+use crate::any::{Demand, Provider, TypeId};
 use crate::backtrace::Backtrace;
 use crate::borrow::Cow;
 use crate::cell;
@@ -295,6 +295,85 @@ pub trait Error: Debug + Display {
     fn cause(&self) -> Option<&dyn Error> {
         self.source()
     }
+
+    /// Provides type based access to context intended for error reports.
+    ///
+    /// Used in conjunction with [`Demand::provide_value`] and [`Demand::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;
+    ///
+    /// #[derive(Debug)]
+    /// struct MyBacktrace {
+    ///     // ...
+    /// }
+    ///
+    /// impl MyBacktrace {
+    ///     fn new() -> MyBacktrace {
+    ///         // ...
+    ///         # MyBacktrace {}
+    ///     }
+    /// }
+    ///
+    /// #[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,
+    /// }
+    ///
+    /// 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, req: &mut Demand<'a>) {
+    ///         req
+    ///             .provide_ref::<MyBacktrace>(&self.backtrace)
+    ///             .provide_ref::<dyn std::error::Error + 'static>(&self.source);
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let backtrace = MyBacktrace::new();
+    ///     let source = SourceError {};
+    ///     let error = Error { source, backtrace };
+    ///     let dyn_error = &error as &dyn std::error::Error;
+    ///     let backtrace_ref = dyn_error.request_ref::<MyBacktrace>().unwrap();
+    ///
+    ///     assert!(core::ptr::eq(&error.backtrace, backtrace_ref));
+    /// }
+    /// ```
+    #[unstable(feature = "error_generic_member_access", issue = "none")]
+    #[allow(unused_variables)]
+    fn provide<'a>(&'a self, req: &mut Demand<'a>) {}
+}
+
+#[unstable(feature = "error_generic_member_access", issue = "none")]
+impl Provider for dyn Error + 'static {
+    fn provide<'a>(&'a self, req: &mut Demand<'a>) {
+        self.provide(req)
+    }
 }
 
 mod private {
@@ -831,6 +910,18 @@ impl dyn Error + 'static {
             None
         }
     }
+
+    /// Request a reference of type `T` as context about this error.
+    #[unstable(feature = "error_generic_member_access", issue = "none")]
+    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
+        core::any::request_ref(self)
+    }
+
+    /// Request a value of type `T` as context about this error.
+    #[unstable(feature = "error_generic_member_access", issue = "none")]
+    pub fn request_value<T: 'static>(&self) -> Option<T> {
+        core::any::request_value(self)
+    }
 }
 
 impl dyn Error + 'static + Send {
@@ -854,6 +945,18 @@ 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 = "none")]
+    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
+        <dyn Error + 'static>::request_ref(self)
+    }
+
+    /// Request a value of type `T` as context about this error.
+    #[unstable(feature = "error_generic_member_access", issue = "none")]
+    pub fn request_value<T: 'static>(&self) -> Option<T> {
+        <dyn Error + 'static>::request_value(self)
+    }
 }
 
 impl dyn Error + 'static + Send + Sync {
@@ -877,6 +980,18 @@ 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 = "none")]
+    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
+        <dyn Error + 'static>::request_ref(self)
+    }
+
+    /// Request a value of type `T` as context about this error.
+    #[unstable(feature = "error_generic_member_access", issue = "none")]
+    pub fn request_value<T: 'static>(&self) -> Option<T> {
+        <dyn Error + 'static>::request_value(self)
+    }
 }
 
 impl dyn Error {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 244597950fa..40c4f6dec0e 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -286,6 +286,7 @@
 #![feature(panic_internals)]
 #![feature(portable_simd)]
 #![feature(prelude_2024)]
+#![feature(provide_any)]
 #![feature(ptr_as_uninit)]
 #![feature(raw_os_nonzero)]
 #![feature(slice_internals)]