miette icon indicating copy to clipboard operation
miette copied to clipboard

Merge labels from another diagnostic

Open gavrilikhin-d opened this issue 9 months ago • 0 comments

Sometimes, I want to construct a bigger error from several related ones. It happens either from convenience reasons, or from technical ones (part of the error may be located in another file)

There is an example from my code:

/// Show type in diagnostic
#[derive(Error, Diagnostic, Debug, Clone, PartialEq)]
#[error("{ty}")]
pub struct TypeWithSpan {
    /// Type to show
    pub ty: Type,

    /// Span of expected type
    #[label("this has `{ty}` type")]
    pub at: SourceSpan,

    // TODO: change to `Option<SourceFile>`
    /// Source code of the module, this type is located at
    #[source_code]
    pub source_code: Option<String>,
}

/// Diagnostic for not convertible types
#[derive(Error, Diagnostic, Debug, Clone, PartialEq)]
#[error("expected `{expected}` type, got `{got}`")]
#[diagnostic(code(semantics::type_mismatch))]
pub struct TypeMismatch {
    /// Expected type
    pub expected: TypeWithSpan,
    /// Real type
    pub got: TypeWithSpan,
}

Declaration of type and its usage may be splited in different files, so there should be two errors. However, logically it's a single TypeMismatch error.

I could use:

#[related]
errors: Vec<TypeWithSpan>

But this will decrease type safety, as I know beforehand that this error consist from exactly two errors.

Hence I propose syntax like this to merge labels from another diagnostics:

#[derive(Error, Diagnostic, Debug, Clone, PartialEq)]
#[error("expected `{expected}` type, got `{got}`")]
#[diagnostic(code(semantics::type_mismatch))]
pub struct TypeMismatch {
    #[related] // or #[labels]
    pub expected: TypeWithSpan,
    #[related] // or #[labels]
    pub got: TypeWithSpan,
}

gavrilikhin-d avatar Oct 05 '23 16:10 gavrilikhin-d