shepmaster / snafu

Easily assign underlying errors into domain-specific errors while adding context
https://docs.rs/snafu/
Apache License 2.0
1.4k stars 60 forks source link

keep `Backtrace` when converting from other Snafu error #313

Closed Anton-4 closed 2 years ago

Anton-4 commented 2 years ago

Hi, I'm really enjoying snafu, thanks for creating and maintaining it :heart:

When converting one Snafu error to another one, I want to keep the Backtrace. However, I can only acquire a reference using the backtrace() function that can not be dereferenced, because Backtrace does not implement Copy. Is there any way to achieve my intended goal?

use snafu::{Backtrace, ErrorCompat, Snafu};

#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
pub enum FooError {

    #[snafu(display("BarError: {}", msg))]
    BarErrorBacktrace { msg: String, backtrace: Backtrace },

    #[snafu(display("BarError: {}", msg))]
    BarErrorNoBacktrace { msg: String },
}

#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
pub enum BarError {

    #[snafu(display("HelloError: {}", msg))]
    HelloError { msg: String },
}

impl From<BarError> for FooError {
    fn from(bar_err: BarError) -> Self {
        let msg = format!("{}", bar_err);

        if let Some(backtrace_ref) = bar_err.backtrace() {
            Self::BarErrorBacktrace {
                msg,
                backtrace: *backtrace_ref
            }
        } else {
            Self::BarErrorNoBacktrace {
                msg
            }
        }
    }
}
shepmaster commented 2 years ago

I’m not following exactly what you want… check out the section on delegating backtraces in https://docs.rs/snafu/0.6.10/snafu/guide/attributes/index.html#controlling-backtraces

Also, if you own an instance (bar_err: BarError) you can match on it and take ownership of the backtrace. Nothing SNAFU specific; regular Rust.

Anton-4 commented 2 years ago

delegating backtraces is what I needed, thanks @shepmaster :)