From 58d2170fc1e4cad4fbcb405aa64cb36d2d9c20e7 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 13 Jun 2022 14:10:25 -0700 Subject: [PATCH 1/4] Add provider API to error trait --- std/src/error.rs | 116 ++++++++++++++++++++++++++++++++++++++++++++++- std/src/lib.rs | 1 + 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/std/src/error.rs b/std/src/error.rs index 87f213b16..3d7d81917 100644 --- a/std/src/error.rs +++ b/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::(&self.backtrace) + /// .provide_ref::(&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::().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(&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(&self) -> Option { + core::any::request_value(self) + } } impl dyn Error + 'static + Send { @@ -854,6 +944,18 @@ impl dyn Error + 'static + Send { pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } + + /// Request a reference to context of type `T`. + #[unstable(feature = "generic_member_access", issue = "none")] + pub fn request_ref(&self) -> Option<&T> { + ::request_ref(self) + } + + /// Request a value to context of type `T`. + #[unstable(feature = "generic_member_access", issue = "none")] + pub fn request_value(&self) -> Option { + ::request_value(self) + } } impl dyn Error + 'static + Send + Sync { @@ -877,6 +979,18 @@ impl dyn Error + 'static + Send + Sync { pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } + + /// Request a reference to context of type `T`. + #[unstable(feature = "generic_member_access", issue = "none")] + pub fn request_ref(&self) -> Option<&T> { + ::request_ref(self) + } + + /// Request a value to context of type `T`. + #[unstable(feature = "generic_member_access", issue = "none")] + pub fn request_value(&self) -> Option { + ::request_value(self) + } } impl dyn Error { diff --git a/std/src/lib.rs b/std/src/lib.rs index 7da9f248c..c46752cc6 100644 --- a/std/src/lib.rs +++ b/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)] From 4b98418fcc4307bb6b8979587980e02ebda21504 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 13 Jun 2022 14:15:05 -0700 Subject: [PATCH 2/4] remove outdated references --- std/src/error.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/std/src/error.rs b/std/src/error.rs index 3d7d81917..e5cc00809 100644 --- a/std/src/error.rs +++ b/std/src/error.rs @@ -298,14 +298,13 @@ pub trait Error: Debug + Display { /// Provides type based access to context intended for error reports. /// - /// Used in conjunction with [`context`] and [`context_ref`] to extract + /// Used in conjunction with [`provide_value`] and [`provide_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; /// From cfe2fc33eca9847064fb2c61f72f4cf1da16d1e5 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 13 Jun 2022 14:47:51 -0700 Subject: [PATCH 3/4] fix broken doc comment --- std/src/error.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/std/src/error.rs b/std/src/error.rs index e5cc00809..6ad04e3f9 100644 --- a/std/src/error.rs +++ b/std/src/error.rs @@ -298,13 +298,14 @@ pub trait Error: Debug + Display { /// Provides type based access to context intended for error reports. /// - /// Used in conjunction with [`provide_value`] and [`provide_ref`] to extract + /// 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; /// @@ -363,11 +364,11 @@ pub trait Error: Debug + Display { /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); /// } /// ``` - #[unstable(feature = "generic_member_access", issue = "none")] + #[unstable(feature = "error_generic_member_access", issue = "none")] fn provide<'a>(&'a self, _req: &mut Demand<'a>) {} } -#[unstable(feature = "generic_member_access", issue = "none")] +#[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) @@ -910,13 +911,13 @@ impl dyn Error + 'static { } /// Request a reference to context of type `T`. - #[unstable(feature = "generic_member_access", issue = "none")] + #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_ref(&self) -> Option<&T> { core::any::request_ref(self) } /// Request a value to context of type `T`. - #[unstable(feature = "generic_member_access", issue = "none")] + #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_value(&self) -> Option { core::any::request_value(self) } @@ -945,13 +946,13 @@ impl dyn Error + 'static + Send { } /// Request a reference to context of type `T`. - #[unstable(feature = "generic_member_access", issue = "none")] + #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_ref(&self) -> Option<&T> { ::request_ref(self) } /// Request a value to context of type `T`. - #[unstable(feature = "generic_member_access", issue = "none")] + #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_value(&self) -> Option { ::request_value(self) } @@ -980,13 +981,13 @@ impl dyn Error + 'static + Send + Sync { } /// Request a reference to context of type `T`. - #[unstable(feature = "generic_member_access", issue = "none")] + #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_ref(&self) -> Option<&T> { ::request_ref(self) } /// Request a value to context of type `T`. - #[unstable(feature = "generic_member_access", issue = "none")] + #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_value(&self) -> Option { ::request_value(self) } From 962efb59de9270257a9c5d915b941b3b5ae2ac26 Mon Sep 17 00:00:00 2001 From: Jane Losare-Lusby Date: Mon, 11 Jul 2022 19:18:56 +0000 Subject: [PATCH 4/4] apply suggestions from code review --- std/src/error.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/std/src/error.rs b/std/src/error.rs index 6ad04e3f9..57f16f951 100644 --- a/std/src/error.rs +++ b/std/src/error.rs @@ -365,7 +365,8 @@ pub trait Error: Debug + Display { /// } /// ``` #[unstable(feature = "error_generic_member_access", issue = "none")] - fn provide<'a>(&'a self, _req: &mut Demand<'a>) {} + #[allow(unused_variables)] + fn provide<'a>(&'a self, req: &mut Demand<'a>) {} } #[unstable(feature = "error_generic_member_access", issue = "none")] @@ -910,13 +911,13 @@ impl dyn Error + 'static { } } - /// Request a reference to context of type `T`. + /// Request a reference of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_ref(&self) -> Option<&T> { core::any::request_ref(self) } - /// Request a value to context of type `T`. + /// Request a value of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_value(&self) -> Option { core::any::request_value(self) @@ -945,13 +946,13 @@ impl dyn Error + 'static + Send { ::downcast_mut::(self) } - /// Request a reference to context of type `T`. + /// Request a reference of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_ref(&self) -> Option<&T> { ::request_ref(self) } - /// Request a value to context of type `T`. + /// Request a value of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_value(&self) -> Option { ::request_value(self) @@ -980,13 +981,13 @@ impl dyn Error + 'static + Send + Sync { ::downcast_mut::(self) } - /// Request a reference to context of type `T`. + /// Request a reference of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_ref(&self) -> Option<&T> { ::request_ref(self) } - /// Request a value to context of type `T`. + /// Request a value of type `T` as context about this error. #[unstable(feature = "error_generic_member_access", issue = "none")] pub fn request_value(&self) -> Option { ::request_value(self)