about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJane Lusby <jlusby@yaah.dev>2022-06-13 14:10:25 -0700
committerJane Lusby <jlusby@yaah.dev>2022-06-13 14:10:25 -0700
commit03999c23944e5d06cab3ddc6919c5f98b494aad0 (patch)
tree9d63c23c53bdf6624be0f393e035a264148e652c
parent083721a1a7365d3afe1521cd2661b2201aac0450 (diff)
downloadrust-03999c23944e5d06cab3ddc6919c5f98b494aad0.tar.gz
rust-03999c23944e5d06cab3ddc6919c5f98b494aad0.zip
Add provider API to error trait
-rw-r--r--library/std/src/error.rs116
-rw-r--r--library/std/src/lib.rs1
2 files changed, 116 insertions, 1 deletions
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 87f213b1608..3d7d8191770 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,84 @@ 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 [`context`] and [`context_ref`] to extract
+    /// references to member variables from `dyn Error` trait objects.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// #![feature(provide_any)]
+    /// #![feature(error_in_core)]
+    /// 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 = "generic_member_access", issue = "none")]
+    fn provide<'a>(&'a self, _req: &mut Demand<'a>) {}
+}
+
+#[unstable(feature = "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 +909,18 @@ impl dyn Error + 'static {
             None
         }
     }
+
+    /// Request a reference to context of type `T`.
+    #[unstable(feature = "generic_member_access", issue = "none")]
+    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
+        core::any::request_ref(self)
+    }
+
+    /// Request a value to context of type `T`.
+    #[unstable(feature = "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 +944,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 to context of type `T`.
+    #[unstable(feature = "generic_member_access", issue = "none")]
+    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
+        <dyn Error + 'static>::request_ref(self)
+    }
+
+    /// Request a value to context of type `T`.
+    #[unstable(feature = "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 +979,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 to context of type `T`.
+    #[unstable(feature = "generic_member_access", issue = "none")]
+    pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
+        <dyn Error + 'static>::request_ref(self)
+    }
+
+    /// Request a value to context of type `T`.
+    #[unstable(feature = "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 7da9f248c87..c46752cc6f9 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -284,6 +284,7 @@
 #![feature(panic_internals)]
 #![feature(portable_simd)]
 #![feature(prelude_2024)]
+#![feature(provide_any)]
 #![feature(ptr_as_uninit)]
 #![feature(raw_os_nonzero)]
 #![feature(slice_internals)]