mirror of
https://github.com/eyre-rs/eyre.git
synced 2025-09-27 04:50:50 +00:00
feat: basic backtrace propagation
This commit is contained in:
parent
29aec58099
commit
b52dba1323
@ -1,8 +1,9 @@
|
||||
#[cfg(backtrace)]
|
||||
pub(crate) use std::backtrace::Backtrace;
|
||||
pub use std::backtrace::Backtrace;
|
||||
|
||||
#[cfg(not(backtrace))]
|
||||
pub(crate) enum Backtrace {}
|
||||
#[derive(Debug)]
|
||||
pub enum Backtrace {}
|
||||
|
||||
#[cfg(backtrace)]
|
||||
macro_rules! backtrace_if_absent {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::Report;
|
||||
use crate::{builder::ReportBuilder, Report};
|
||||
|
||||
/// Convert this result into an eyre [`Report`](crate::Report) result
|
||||
///
|
||||
@ -6,12 +6,7 @@ use crate::Report;
|
||||
/// [`Error`](std::error::Error) is not yet available.
|
||||
pub trait IntoEyre<T> {
|
||||
/// Convert this result into an eyre [`Report`](crate::Report) result
|
||||
fn into_eyre(self) -> crate::Result<T>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
fn into_eyre(self) -> crate::Result<T>;
|
||||
}
|
||||
|
||||
/// See: [`IntoEyre`]
|
||||
@ -19,25 +14,27 @@ pub trait IntoEyre<T> {
|
||||
/// Error type automatically implements `into_eyre` for `Result<T, E>`
|
||||
pub trait IntoEyreReport {
|
||||
/// Convert this error into an eyre [`Report`](crate::Report)
|
||||
fn into_eyre_report(self) -> Report
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
#[track_caller]
|
||||
fn into_eyre_report(self) -> Report;
|
||||
}
|
||||
|
||||
impl<T, E> IntoEyre<T> for Result<T, E>
|
||||
where
|
||||
E: IntoEyreReport,
|
||||
{
|
||||
#[track_caller]
|
||||
fn into_eyre(self) -> crate::Result<T> {
|
||||
self.map_err(E::into_eyre_report)
|
||||
// Use a manual match to keep backtrace
|
||||
match self {
|
||||
Ok(v) => Ok(v),
|
||||
Err(err) => Err(err.into_eyre_report()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "anyhow-compat")]
|
||||
impl IntoEyreReport for anyhow::Error {
|
||||
#[track_caller]
|
||||
fn into_eyre_report(self) -> Report
|
||||
where
|
||||
Self: Sized,
|
||||
@ -60,7 +57,13 @@ impl IntoEyreReport for anyhow::Error {
|
||||
.next()
|
||||
.expect("Error chain contains at least one error");
|
||||
|
||||
let report = Report::msg(head.to_string());
|
||||
#[cfg(backtrace)]
|
||||
let report = ReportBuilder::default()
|
||||
.with_backtrace(self.backtrace())
|
||||
.msg(head.to_string());
|
||||
|
||||
#[cfg(not(backtrace))]
|
||||
let report = ReportBuilder::default().msg(head.to_string());
|
||||
// chai
|
||||
// eprintln!("{:?}", chain.map(|v| v.to_string()).collect::<Vec<_>>());
|
||||
|
||||
|
@ -1,24 +1,64 @@
|
||||
use anyhow::Context;
|
||||
use eyre::WrapErr;
|
||||
use std::fmt::Display;
|
||||
|
||||
use eyre::{compat::IntoEyre, Report};
|
||||
|
||||
fn this_function_fails() -> anyhow::Result<()> {
|
||||
anyhow::bail!("Ouch!")
|
||||
#[derive(Debug)]
|
||||
struct RootError;
|
||||
|
||||
impl Display for RootError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "RootError")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for RootError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "anyhow-compat")]
|
||||
fn this_function_fails() -> anyhow::Result<()> {
|
||||
use anyhow::Context;
|
||||
|
||||
Err(RootError).context("Ouch!").context("Anyhow context A")
|
||||
}
|
||||
|
||||
#[cfg(feature = "anyhow-compat")]
|
||||
fn bubble() -> eyre::Result<()> {
|
||||
use anyhow::Context;
|
||||
use eyre::WrapErr;
|
||||
this_function_fails()
|
||||
.context("Anyhow::context")
|
||||
.context("Anyhow context B")
|
||||
.into_eyre()
|
||||
.wrap_err("Eyre::wrap_err")?;
|
||||
.wrap_err("Eyre context A")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "anyhow-compat")]
|
||||
#[test]
|
||||
fn anyhow_conversion() {
|
||||
let error: Report = bubble().unwrap_err();
|
||||
// let error = Report::msg("A").wrap_err("B").wrap_err("C");
|
||||
use eyre::WrapErr;
|
||||
let error: Report = bubble().wrap_err("Eyre context B").unwrap_err();
|
||||
|
||||
eprintln!("{error:?}");
|
||||
|
||||
let chain = error.chain().map(ToString::to_string).collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
chain,
|
||||
[
|
||||
"Eyre context B",
|
||||
"Eyre context A",
|
||||
// Anyhow context
|
||||
"Anyhow context B",
|
||||
"Anyhow context A",
|
||||
// Anyhow error
|
||||
"Ouch!",
|
||||
// Original concrete error, shows up in chain too
|
||||
"RootError"
|
||||
]
|
||||
);
|
||||
|
||||
// let error = Report::msg("A").wrap_err("B").wrap_err("C");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user