miette icon indicating copy to clipboard operation
miette copied to clipboard

Limitations of downcast_ref

Open martinstuder opened this issue 1 month ago • 4 comments

I encounter situations where unwrap_err().downcast_ref() on a miette::Result always returns None despite the correct error type being contained. The situation typically happens in tests where the error type that I'm trying to downcast to is defined in the same workspace member / package. If the error type is defined in another workspace member, then downcast_ref seems to work just fine. I'm wondering why this is the case and whether there are specific limitations that need to be considered.

My error types are typically defined as follows:

use miette::Diagnostic;
use thiserror::Error;

#[derive(Debug, Clone, PartialEq, Error, Diagnostic)]
pub enum MyError {
    #[error("some error")]
    #[diagnostic(code(myerror::some_error))]
    SomeError,
}

And tests that I'm referring to have the following structure:

#[cfg(test)]
mod tests {
    #[test]
    fn test_some_error() {
        assert_eq!(do_something().unwrap_err().downcast_ref(), Some(&MyError::SomeError));
    }
}

where do_something() returns a miette::Result.

martinstuder avatar Nov 12 '25 16:11 martinstuder

Do you have a full, self-contained repro of this? What rustc version? And so on I tried to repro it like this, but without luck:


#[derive(Debug, Clone, PartialEq, thiserror::Error, Diagnostic)]
pub enum MyError {
    #[error("some error")]
    #[diagnostic(code(myerror::some_error))]
    SomeError,
}

fn bail_repro() -> miette::Result<()>
{
    miette::Result::Err(MyError::SomeError.into())
}

#[test]
fn test_downcast_bug_repro() {
    assert_eq!(bail_repro().unwrap_err().downcast_ref(), Some(&MyError::SomeError));
}

cgettys-microsoft avatar Nov 15 '25 00:11 cgettys-microsoft

This is with rustc 1.91.1. I tried to come up with a minimal self-contained repro but failed. Maybe it's not some form of TypeId instability that I suspected, but rather my error type is getting wrapped somewhere (and I haven't found where that happens yet). Which brings me to another question: is it generally better practice with miette to test for the error code (using .unwrap_err().code()) instead of checking for the concrete error type? This seems to work reliably in my case.

martinstuder avatar Nov 16 '25 08:11 martinstuder

I have no idea, I've contributed some but am not all-knowing :). Have you tried running the test in question under Miri? the downcasting I believe involves some unsafe code (I believe it's under eyreish?: https://github.com/zkat/miette/tree/df7bcfa17d9c0813286050ee245d5c3d94653f1c/src/eyreish). would be good to rule out UB.

cgettys-microsoft avatar Nov 17 '25 01:11 cgettys-microsoft

Thanks for the suggestion. I can confirm that Miri doesn't flag any UB issues.

martinstuder avatar Nov 19 '25 14:11 martinstuder