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("...");
    }
This commit is contained in:
David Tolnay 2019-10-27 16:02:50 -07:00
parent 8885e93ca6
commit a2846fd345
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82

View File

@ -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::<ContextError<C, Error>>,
object_drop_front: object_drop_front::<ContextError<C, Error>>,
object_ref: object_ref::<ContextError<C, Error>>,
object_mut: object_mut::<ContextError<C, Error>>,
object_boxed: object_boxed::<ContextError<C, Error>>,
object_is: object_is::<ContextError<C, Error>>,
};
// 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.