From a2846fd34539d3ae3cc159c496a0dea14e07db61 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 27 Oct 2019 16:02:50 -0700 Subject: [PATCH] Eliminate backtrace_if_absent in Error::context This avoids stepping through the list of causes when adding context to the anyhow::Error type which is known to already hold a backtrace. Reduces the release-mode time of the following loop from 4 seconds to 4 milliseconds. let mut err = anyhow!("..."); for _ in 0..25000 { err = err.context("..."); } --- src/error.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/error.rs b/src/error.rs index afe006c..bb09fe4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -167,10 +167,25 @@ impl Error { where C: Display + Send + Sync + 'static, { - Error::new(ContextError { + let error = ContextError { context, error: self, - }) + }; + + let vtable = &ErrorVTable { + object_drop: object_drop::>, + object_drop_front: object_drop_front::>, + object_ref: object_ref::>, + object_mut: object_mut::>, + object_boxed: object_boxed::>, + object_is: object_is::>, + }; + + // As the cause is anyhow::Error, we already have a backtrace for it. + let backtrace = None; + + // Safety: passing vtable that operates on the right type. + unsafe { Error::construct(error, vtable, backtrace) } } /// Get the backtrace for this Error.