pub struct Code { /* private fields */ }Expand description
A diagnostic code such as E0001, T0042, or KRA0013: an uppercase
prefix naming the registry that owns it, and a four-digit number within that
registry.
A code is the stable identity of a kind of diagnostic. Messages can be
reworded between releases; the code does not change, so tools key on it: an
editor links it to documentation, a lint configuration silences it, a test
asserts on it, and a filter separates lexical errors from parse errors by
range without parsing message text. The renderer shows it in the header,
rustc-style (error[E0001]: …), and the JSON output carries it as a string.
§Format
One to four ASCII uppercase letters (A–Z) followed by a number from 0
to 9999, always written with exactly four digits: Code::new("E", 1)
displays as E0001. The fixed width means a code’s text and its value
round-trip exactly (Code::parse accepts precisely what Display
writes), and codes of one prefix sort the same as text and as numbers.
§Registries and ranges
The prefix names the registry; the number range within it names the phase.
Codes in use across the -lang family:
| Prefix | Owner | Range |
|---|---|---|
E | Runtime errors: OPS | E0001–E0099 |
E | Runtime errors: LSB | E0100–E0199 |
T | Type checking (typeck-lang) | T0001– |
A language front end takes its own prefix (Kraken uses KRA) and is
recommended to split its numbers by phase, so that “is this a lexical
error?” is a range check:
| Range | Phase |
|---|---|
0001–0999 | Lexical: bad characters, unterminated literals, malformed numbers |
1000–1999 | Parse: unexpected or missing tokens, unbalanced delimiters |
2000–7999 | Semantic: name resolution, types, borrow and flow checks |
8000–8999 | Lints and style warnings |
9000–9999 | Internal and tool errors (9999: internal compiler error) |
This is a convention, not an enforced rule: the crate accepts any
well-formed code. See docs/API.md for the full guidance.
§Examples
use diag_lang::Code;
// A registry declares its codes as constants.
const UNTERMINATED_STRING: Code = Code::new("KRA", 1).unwrap();
const UNEXPECTED_TOKEN: Code = Code::new("KRA", 1000).unwrap();
assert_eq!(UNTERMINATED_STRING.to_string(), "KRA0001");
assert_eq!(UNEXPECTED_TOKEN.prefix(), "KRA");
assert_eq!(UNEXPECTED_TOKEN.number(), 1000);
// The phase is a range check on the number.
let is_lexical = |c: Code| c.prefix() == "KRA" && c.number() < 1000;
assert!(is_lexical(UNTERMINATED_STRING));
assert!(!is_lexical(UNEXPECTED_TOKEN));
// Text and value round-trip exactly.
assert_eq!(Code::parse("KRA0001"), Some(UNTERMINATED_STRING));Implementations§
Source§impl Code
impl Code
Sourcepub const fn new(prefix: &str, number: u16) -> Option<Self>
pub const fn new(prefix: &str, number: u16) -> Option<Self>
Builds the code prefix + number, or None if either is out of range.
prefix must be one to four ASCII uppercase letters and number at
most 9999. The function is const, so a registry can declare its codes
as constants with Code::new("E", 1).unwrap(), where a malformed code is
a compile error rather than a runtime failure.
§Examples
use diag_lang::Code;
const ARITH_OVERFLOW: Code = Code::new("E", 1).unwrap();
assert_eq!(ARITH_OVERFLOW.to_string(), "E0001");
assert_eq!(Code::new("e", 1), None); // lowercase
assert_eq!(Code::new("", 1), None); // no prefix
assert_eq!(Code::new("ABCDE", 1), None); // prefix too long
assert_eq!(Code::new("E", 10_000), None); // more than four digitsSourcepub const fn parse(text: &str) -> Option<Self>
pub const fn parse(text: &str) -> Option<Self>
Parses a code written the way Display writes it: one
to four ASCII uppercase letters followed by exactly four digits.
Returns None for anything else, including surrounding whitespace, a
lowercase prefix, or a number with more or fewer than four digits, so
parse(&code.to_string()) == Some(code) for every code and nothing else
parses.
§Examples
use diag_lang::Code;
let code = Code::parse("T0042").unwrap();
assert_eq!((code.prefix(), code.number()), ("T", 42));
assert_eq!(Code::parse("T42"), None); // four digits, always
assert_eq!(Code::parse("T00042"), None);
assert_eq!(Code::parse("0042"), None); // a prefix is required