pub struct Diagnostic { /* private fields */ }Expand description
One thing a compiler stage has to say about the source: a Severity, a
headline message, a primary Label pointing at the span it concerns, and
optionally secondary labels for related locations and trailing note/help lines.
A Diagnostic is the unit a lexer, parser, or type checker emits and a
Renderer turns into caret-annotated output. Constructing
one is cheap — it allocates only what the message, labels, and notes require —
because it is on the front-end’s hot path. The primary label is supplied at
construction, so a diagnostic always knows where it points; secondary labels
and notes are added with the chainable with_* builders.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(
Severity::Error,
"mismatched types",
Label::new(Span::new(20, 27), "expected `i32`, found `&str`"),
)
.with_secondary(Label::new(Span::new(8, 11), "expected due to this"))
.with_note("string literals have type `&str`")
.with_help("convert with `.parse()`");
assert_eq!(diag.secondary().len(), 1);
assert_eq!(diag.notes().count(), 1);
assert_eq!(diag.help().count(), 1);Implementations§
Source§impl Diagnostic
impl Diagnostic
Sourcepub fn new(
severity: Severity,
message: impl Into<Box<str>>,
primary: Label,
) -> Diagnostic
pub fn new( severity: Severity, message: impl Into<Box<str>>, primary: Label, ) -> Diagnostic
Builds a diagnostic at severity, headed by message, pointing at
primary.
The message is taken by value (a &str or an owned String), so the
diagnostic owns its text. The primary label is required: a diagnostic
always has a span to render a caret under, which keeps the type total and
the renderer free of a “no location” branch. Secondary labels and notes
start empty; add them with with_secondary,
with_note, and with_help.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(
Severity::Warning,
"unused variable `x`",
Label::new(Span::new(4, 5), "first defined here"),
);
assert_eq!(diag.severity(), Severity::Warning);
assert!(diag.secondary().is_empty());Sourcepub fn with_secondary(self, label: Label) -> Diagnostic
pub fn with_secondary(self, label: Label) -> Diagnostic
Adds a secondary label, returning the diagnostic for chaining.
Secondary labels mark locations related to the primary one — “expected
because of this”, “first defined here”. A renderer draws them with a -
underline to distinguish them from the primary ^. Any number may be
added; they render in a stable order driven by where they point, not by the
order they were added.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(
Severity::Error,
"duplicate definition",
Label::new(Span::new(30, 33), "redefined here"),
)
.with_secondary(Label::new(Span::new(4, 7), "first defined here"));
assert_eq!(diag.secondary().len(), 1);Sourcepub fn with_note(self, note: impl Into<Box<str>>) -> Diagnostic
pub fn with_note(self, note: impl Into<Box<str>>) -> Diagnostic
Adds a trailing note, returning the diagnostic for chaining.
A note is neutral context with no span of its own; a renderer prints it on
its own line below the frame, marked note:. Notes render in the order they
are added, after any help lines’ siblings — see
with_help.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(Severity::Error, "boom", Label::unlabelled(Span::empty(0)))
.with_note("the value was moved on the previous line");
assert_eq!(diag.notes().next(), Some("the value was moved on the previous line"));Sourcepub fn with_help(self, help: impl Into<Box<str>>) -> Diagnostic
pub fn with_help(self, help: impl Into<Box<str>>) -> Diagnostic
Adds a trailing help line, returning the diagnostic for chaining.
A help line is a suggestion toward a fix; a renderer prints it below the
notes, marked help:. Help lines render in the order they are added.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(Severity::Error, "boom", Label::unlabelled(Span::empty(0)))
.with_help("add a semicolon");
assert_eq!(diag.help().next(), Some("add a semicolon"));Sourcepub const fn severity(&self) -> Severity
pub const fn severity(&self) -> Severity
Returns the level this diagnostic reports at.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(Severity::Error, "boom", Label::unlabelled(Span::empty(0)));
assert_eq!(diag.severity(), Severity::Error);Sourcepub fn message(&self) -> &str
pub fn message(&self) -> &str
Returns the headline message.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(Severity::Error, "boom", Label::unlabelled(Span::empty(0)));
assert_eq!(diag.message(), "boom");Sourcepub const fn primary(&self) -> &Label
pub const fn primary(&self) -> &Label
Returns the primary label — the span the caret underlines.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(
Severity::Error,
"boom",
Label::new(Span::new(2, 5), "right here"),
);
assert_eq!(diag.primary().message(), "right here");Sourcepub fn secondary(&self) -> &[Label]
pub fn secondary(&self) -> &[Label]
Returns the secondary labels, in the order they were added.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(Severity::Error, "boom", Label::unlabelled(Span::empty(0)))
.with_secondary(Label::new(Span::new(1, 2), "related"));
assert_eq!(diag.secondary()[0].message(), "related");Sourcepub fn notes(&self) -> impl ExactSizeIterator
pub fn notes(&self) -> impl ExactSizeIterator
Iterates over the note lines, in the order they were added.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(Severity::Error, "boom", Label::unlabelled(Span::empty(0)))
.with_note("one")
.with_note("two");
assert_eq!(diag.notes().collect::<Vec<_>>(), ["one", "two"]);Sourcepub fn help(&self) -> impl ExactSizeIterator
pub fn help(&self) -> impl ExactSizeIterator
Iterates over the help lines, in the order they were added.
§Examples
use diag_lang::{Diagnostic, Label, Severity};
use span_lang::Span;
let diag = Diagnostic::new(Severity::Error, "boom", Label::unlabelled(Span::empty(0)))
.with_help("try this");
assert_eq!(diag.help().collect::<Vec<_>>(), ["try this"]);Trait Implementations§
Source§impl Clone for Diagnostic
impl Clone for Diagnostic
Source§fn clone(&self) -> Diagnostic
fn clone(&self) -> Diagnostic
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for Diagnostic
impl Debug for Diagnostic
impl Eq for Diagnostic
Source§impl PartialEq for Diagnostic
impl PartialEq for Diagnostic
Source§fn eq(&self, other: &Diagnostic) -> bool
fn eq(&self, other: &Diagnostic) -> bool
self and other values to be equal, and is used by ==.