miette
miette copied to clipboard
Bad span pointing when single line span supersets a prior span
Excerpt:
use miette::{Diagnostic, ErrReport, Result, SourceSpan};
use thiserror::Error;
#[derive(Debug, Error, Diagnostic)]
#[diagnostic(severity(warning))]
pub enum Warning {
#[error("invalid target directive specified")]
#[diagnostic(code(tracing_filter::simple::Warning::InvalidTarget), url(docsrs))]
InvalidTarget {
#[label("this `=` is not allowed ...")]
equals: SourceSpan,
#[label("... in this target directive")]
target: SourceSpan,
},
}
pub fn main() -> Result<()> {
Err(ErrReport::from(Warning::InvalidTarget {
equals: (5..6).into(),
target: (0..12).into(),
})
.with_source_code("crate=target=warn"))
}
Error: tracing_filter::simple::Warning::InvalidTarget (link)
⚠ invalid target directive specified
╭────
1 │ crate=target=warn
· ──────┬─────
· │╰── this `=` is not allowed ...
· ╰── ... in this target directive
╰────
This is, admittedly, a rather degenerate case. But the span is clearly pointing not at the desired location.
If the point is after the halfway point, it works:
Error: tracing_filter::simple::Warning::InvalidTarget (link)
⚠ invalid target directive specified
╭────
1 │ xxxxxxxxxxxxxxxxxxxxxxxxxxxx=xx=warn
· ───────────────┬───────────────
· │ ╰── this `=` is not allowed ...
· ╰── ... in this target directive
╰────
but if the point is before the halfway point, it gets shoved "out of the way" of the latter span's stem, arbitrarily far from where it's supposed to point:
Error: tracing_filter::simple::Warning::InvalidTarget (link)
⚠ invalid target directive specified
╭────
1 │ xx=xxxxxxxxxxxxxxxxxxxxxxxxxxxx=warn
· ───────────────┬───────────────
· │╰── this `=` is not allowed ...
· ╰── ... in this target directive
╰────
tbh while it's weird, I'm inclined to mark this as "wontfix". When I was writing this, I intentionally decided not to bother making them overlap because I assumed it would make the rendering logic way too complicated and/or the errors not very readable/helpful. Like, what's the "correct" way to display this? I don't know! Anything I can come up with is awful and I think this is a "don't give miette overlapping spans" sort of thing tbh.
I could've sworn that rustc emitted errors with a large superset span in some cases, but I can't figure out when it occurs or find an example. Specifically, I feel like I've seen:
╭─[1:1]
1 │
2 │ ╭─▶︎ 123456789
3 │ │ 123456789
· │ ──┬─
· │ ╰── inner span
4 │ ├─▶︎ 123456789
· ╰──── outer span
╰────
(GitHub's ▶︎
is slightly more than a cell wide... and I event applied the text presentation selector to remove the emoji presentation default)
The lines for this case don't have to overlap, but miette still chokes rather interestingly. The above is cleaned, and what miette actually gave is completely broken:
╭─[1:1]
1 │
2 │ ╭─▶︎ 123456789
3 │ │╭▶︎ 123456789
· ││ ──┬─
· ││ ╰── inner span
4 │ ├─▶︎ 123456789
· ╰──── outer span
╰────
I'll rethink the structure of these warnings to avoid overlapping the spans, then.
(I think my ideal warning would be smth like
Warning: tracing_filter::simple::Warning::InvalidDirective
⚠ invalid directive specified
╭────
1 │ crate=target=warn
· ┬ ┬
· ╰──────┴─── only one `=` is allowed
╰────
)
The last bug highlighted here (with the two arrow lines in the gutter) is fixed with #316