diff --git a/examples/output.rs b/examples/output.rs index a5e7a86..558373b 100644 --- a/examples/output.rs +++ b/examples/output.rs @@ -4,7 +4,8 @@ fn main0() -> Result<()> { Err(How::new( "The engine broke down" .with("Remember: you aren't good with cars") - .with("Suggestion: call a tow truck"), + .with("Suggestion: call a tow truck") + .with("Foo".with("Bar").with("Baz")), ) .context( "While driving down a road" diff --git a/src/context.rs b/src/context.rs index 7c861ff..95d69f7 100644 --- a/src/context.rs +++ b/src/context.rs @@ -69,6 +69,7 @@ pub enum Detail { #[cfg(feature = "backtrace")] Backtrace(PrivateBacktrace), Error(PrivateError), + Context(Box), } impl Detail { @@ -137,6 +138,7 @@ impl fmt::Display for Detail { write!(f, "{}", bt) }, Self::Error(PrivateError(e)) => e.fmt(f), + Self::Context(c) => c.fmt(f), } } } @@ -154,6 +156,15 @@ pub trait IntoContext: Sized { fn with_caller(self) -> Context { self.with(Location::caller()) } + + #[inline(always)] + #[track_caller] + fn with_backtrace(self) -> Context { + #[cfg(feature = "backtrace")] + return self.with(Detail::backtrace()); + #[cfg(not(feature = "backtrace"))] + self.into_context() + } } impl IntoContext for Context { @@ -166,10 +177,12 @@ impl IntoContext for Context { #[track_caller] #[inline] fn with(mut self, other: impl IntoContext) -> Self { - let mut other = other.into_context(); - self.extra.reserve(1 + other.extra.len()); - self.extra.push(other.detail); - self.extra.append(&mut other.extra); + let other = other.into_context(); + if other.extra.is_empty() { + self.extra.push(other.detail); + } else { + self.extra.push(Detail::Context(other.into())); + } self } } @@ -177,14 +190,14 @@ impl IntoContext for Context { impl IntoContext for String { #[inline(always)] fn into_context(self) -> Context { - Context::new(Detail::String(self)) + Detail::String(self).into_context() } } impl IntoContext for &'static str { #[inline(always)] fn into_context(self) -> Context { - Context::new(Detail::Str(self)) + Detail::Str(self).into_context() } } @@ -208,7 +221,7 @@ impl<'a> IntoContext for &'a Location<'static> { impl IntoContext for Location<'static> { #[inline] fn into_context(self) -> Context { - Context::new(Detail::Location(self)) + Detail::Location(self).into_context() } } @@ -218,14 +231,21 @@ where { #[inline] fn into_context(self) -> Context { - Context::new(Detail::Error(PrivateError(self))) + Detail::Error(PrivateError(self)).into_context() } } impl IntoContext for Arc { #[inline] fn into_context(self) -> Context { - Context::new(Detail::Error(PrivateError(self))) + Detail::Error(PrivateError(self)).into_context() + } +} + +impl IntoContext for Detail { + #[inline(always)] + fn into_context(self) -> Context { + Context::new(self) } }