Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

anyhow's dyn error backtrace disagrees with anyhow::Error::backtrace #231

Closed
guswynn opened this issue Mar 25, 2022 · 2 comments
Closed

Comments

@guswynn
Copy link

guswynn commented Mar 25, 2022

#![feature(backtrace)]
use anyhow;
use thiserror::Error;

#[derive(Error, Debug)]
enum Gus {
    #[error("hmm")]
    Other(
        #[from]
        #[backtrace]
        anyhow::Error,
    ),
}
fn main() {
    use std::error::Error;
    use std::ops::Deref;
    println!("{:?}", Gus::from(anyhow::anyhow!("main")));
    println!("{:?}", Gus::from(anyhow::anyhow!("main")).backtrace());
    println!("{:?}", anyhow::anyhow!("main").deref().backtrace());
}

results in

>printing the error with a backtrace
None
None

Looking briefly at the code, this appears to be at least semi-on-purpose, where the vtable for adhoc errors points to no_backtrace, but it links the backtrace back in somehow? can the ErrorImpl coercion do the same things as

pub(crate) unsafe fn backtrace(this: Ref<Self>) -> &Backtrace {
?

(also, is there a reason the backtrace is only printed for the Debug impl, not the Display impl, should the docs be updated to reflect that?)

@guswynn guswynn changed the title anyhow's dyn error bactrace disagrees with anyhow's dyn error bactrace disagrees with anyhow::Error::backtrace Mar 25, 2022
@guswynn guswynn changed the title anyhow's dyn error bactrace disagrees with anyhow::Error::backtrace anyhow's dyn error bacltrace disagrees with anyhow::Error::backtrace Mar 25, 2022
@guswynn guswynn changed the title anyhow's dyn error bacltrace disagrees with anyhow::Error::backtrace anyhow's dyn error backtrace disagrees with anyhow::Error::backtrace Mar 25, 2022
@dtolnay
Copy link
Owner

dtolnay commented Sep 4, 2022

Updated repro:

#![feature(error_generic_member_access, provide_any)]

use std::any;
use std::backtrace::Backtrace;
use std::ops::Deref;
use thiserror::Error;

#[derive(Error, Debug)]
enum Gus {
    #[error("hmm")]
    Other(
        #[from]
        #[backtrace]
        anyhow::Error,
    ),
}

fn main() {
    println!("{:?}", Gus::from(anyhow::anyhow!("main")));
    println!("{:?}", any::request_ref::<Backtrace>(&Gus::from(anyhow::anyhow!("main"))));
    println!("{:?}", any::request_ref::<Backtrace>(&anyhow::anyhow!("main").deref()));
}
Other(main

Stack backtrace:
   …)
None
None

@dtolnay
Copy link
Owner

dtolnay commented Sep 4, 2022

This is fixed as of thiserror 1.0.34 and anyhow 1.0.64.

Other(main

Stack backtrace:
   …)
Some(Backtrace […])
None

The last one is still None because you've written .deref() which specifically dereferences to the underlying Error impl that the anyhow::Error was constructed from, but the thiserror-generated Error impl has the correct backtrace now. It may be possible to do it for .deref() too but since your issue involves thiserror it doesn't sound like your issue was motivated by that case.

@dtolnay dtolnay closed this as completed Sep 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants