From 6b601f8215606dd2df52d52d05241cc6e8609dc4 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Tue, 7 Apr 2020 14:26:48 -0700 Subject: [PATCH] Propogate context to the top most error when wrapping inner errors (#5) * Propogate context when wrapping errors with Option::take * fix test failure in fmt output * bump version for release --- Cargo.toml | 2 +- src/error.rs | 30 +++++++++++++++++++----------- src/fmt.rs | 10 ++++++++-- src/lib.rs | 2 +- 4 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3523258..2310859 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "eyre" -version = "0.3.6" # remember to update html_root_url +version = "0.3.7" # remember to update html_root_url authors = ["David Tolnay ", "Jane Lusby "] edition = "2018" license = "MIT OR Apache-2.0" diff --git a/src/error.rs b/src/error.rs index 276d07f..809c54a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -93,7 +93,8 @@ where }; // Safety: passing vtable that operates on the right type E. - unsafe { ErrReport::construct(error, vtable) } + let context = Some(C::default(&error)); + unsafe { ErrReport::construct(error, vtable, context) } } pub(crate) fn from_adhoc(message: M) -> Self @@ -114,7 +115,8 @@ where // Safety: MessageError is repr(transparent) so it is okay for the // vtable to allow casting the MessageError to M. - unsafe { ErrReport::construct(error, vtable) } + let context = Some(C::default(&error)); + unsafe { ErrReport::construct(error, vtable, context) } } #[cfg(feature = "std")] @@ -136,13 +138,15 @@ where }; // Safety: passing vtable that operates on the right type. - unsafe { ErrReport::construct(error, vtable) } + let context = Some(C::default(&error)); + unsafe { ErrReport::construct(error, vtable, context) } } #[cfg(feature = "std")] pub(crate) fn from_boxed(error: Box) -> Self { use crate::wrapper::BoxedError; let error = BoxedError(error); + let context = Some(C::default(&error)); let vtable = &ErrorVTable { object_drop: object_drop::, object_ref: object_ref::, @@ -155,7 +159,7 @@ where // Safety: BoxedError is repr(transparent) so it is okay for the vtable // to allow casting to Box. - unsafe { ErrReport::construct(error, vtable) } + unsafe { ErrReport::construct(error, vtable, context) } } // Takes backtrace as argument rather than capturing it here so that the @@ -163,11 +167,10 @@ where // // Unsafe because the given vtable must have sensible behavior on the error // value of type E. - unsafe fn construct(error: E, vtable: &'static ErrorVTable) -> Self + unsafe fn construct(error: E, vtable: &'static ErrorVTable, context: Option) -> Self where E: StdError + Send + Sync + 'static, { - let context = C::default(&error); let inner = Box::new(ErrorImpl { vtable, context, @@ -237,10 +240,11 @@ where /// }) /// } /// ``` - pub fn wrap_err(self, msg: D) -> Self + pub fn wrap_err(mut self, msg: D) -> Self where D: Display + Send + Sync + 'static, { + let context = self.inner.context.take(); let error: ContextError> = ContextError { msg, error: self }; let vtable = &ErrorVTable { @@ -254,7 +258,7 @@ where }; // Safety: passing vtable that operates on the right type. - unsafe { ErrReport::construct(error, vtable) } + unsafe { ErrReport::construct(error, vtable, context) } } /// Get the backtrace for this ErrReport. @@ -433,11 +437,11 @@ where } pub fn context(&self) -> &C { - &self.inner.context + self.inner.context.as_ref().unwrap() } pub fn context_mut(&mut self) -> &mut C { - &mut self.inner.context + self.inner.context.as_mut().unwrap() } } @@ -685,7 +689,7 @@ where C: EyreContext, { vtable: &'static ErrorVTable, - pub(crate) context: C, + pub(crate) context: Option, // NOTE: Don't use directly. Use only through vtable. Erased type may have // different alignment. _object: E, @@ -730,12 +734,16 @@ where pub fn member_ref(&self) -> Option<&T> { self.context + .as_ref() + .unwrap() .member_ref(TypeId::of::())? .downcast_ref::() } pub fn member_mut(&mut self) -> Option<&mut T> { self.context + .as_mut() + .unwrap() .member_mut(TypeId::of::())? .downcast_mut::() } diff --git a/src/fmt.rs b/src/fmt.rs index a3305a9..42e0e57 100644 --- a/src/fmt.rs +++ b/src/fmt.rs @@ -7,10 +7,16 @@ where C: EyreContext, { pub(crate) fn display(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.context.display(self.error(), f) + self.context + .as_ref() + .map(|context| context.display(self.error(), f)) + .unwrap_or_else(|| std::fmt::Display::fmt(self.error(), f)) } pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.context.debug(self.error(), f) + self.context + .as_ref() + .map(|context| context.debug(self.error(), f)) + .unwrap_or_else(|| std::fmt::Debug::fmt(self.error(), f)) } } diff --git a/src/lib.rs b/src/lib.rs index 294c288..47547d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -314,7 +314,7 @@ //! [`anyhow`]: https://github.com/dtolnay/anyhow //! [`tracing_error::SpanTrace`]: https://docs.rs/tracing-error/*/tracing-error/struct.SpanTrace.html -#![doc(html_root_url = "https://docs.rs/eyre/0.3.6")] +#![doc(html_root_url = "https://docs.rs/eyre/0.3.7")] #![cfg_attr(backtrace, feature(backtrace))] #![cfg_attr(not(feature = "std"), no_std)] #![allow(