Adding a Diagnostic
How to add a new tyc::* diagnostic, end to end.
The pattern
Every diagnostic:
- Has a stable code (
tyc::my_new_check). - Is registered once in
tyc-diagnostics. - Is emitted from one or more sites in upstream crates.
- Has a test in the relevant crate.
- Is documented in
docs-site/src/content/docs/diagnostics/.
Walk-through
-
Pick the code name. Conventions: lowercase, snake_case, descriptive. Examples:
nullable_use,non_exhaustive_match,missing_await. -
Register it in
tyc-diagnostics. Add a variant to theDiagnosticenum (or the equivalent — seetyc/crates/tyc-diagnostics/src/lib.rs):#[derive(Diagnostic, thiserror::Error, Debug)]pub enum Diagnostic {// ... existing variants ...#[error("describe the problem in plain English")]#[diagnostic(code(tyc::my_new_check),help("suggest a concrete fix"))]MyNewCheck {#[source_code]src: NamedSource,#[label("primary span")]span: SourceSpan,},} -
Emit it from the check site. In the relevant crate (e.g.
tyc-types), construct the diagnostic and push it onto the diagnostics buffer:diagnostics.push(Diagnostic::MyNewCheck {src: NamedSource::new(file_path, source.to_string()),span: span_for(node),}); -
Add an integration test. In
tyc/tests/(or the relevant crate’stests/), write a small.tyfile that triggers the diagnostic and assert the code appears in the output:#[test]fn my_new_check_fires() {let result = check_str(r#"# source that triggers the diagnostic"#);assert!(result.diagnostics.iter().any(|d| d.code() == "tyc::my_new_check"));} -
Document it. Add an entry to the relevant page under
docs-site/src/content/docs/diagnostics/. Include:- The code name.
- A short description.
- A minimal example that triggers it.
- The recommended fix.
-
Run the workspace tests.
Terminal window cd tyc && cargo test --workspace
Tips
- Search for an existing similar diagnostic and copy its pattern. Style consistency matters for the catalog.
- Make the help message actionable. Not “type mismatch”; “expected
int, foundstr— convert withint(...)or change the annotation”. - Use
[label("...")]annotations on related spans for multi-span diagnostics. The label text shows up in the rendered output. - Test both the positive and negative case. The diagnostic should fire when it should, and not fire when it shouldn’t.
- Keep the code name stable. Once a diagnostic ships, downstream users grep for the code. Renaming it is a breaking change.
Severity
Most diagnostics are error. Warnings are reserved for things that compile but are probably bugs (e.g. async_without_await). The severity is set on the Diagnostic variant; see existing examples for the macro form.
Linking from the catalog
Once documented, link the catalog page from any tour / reference page where it might come up. The cross-linking is what makes the docs navigable.
Where next
- Reading Diagnostics — what the user sees.
- Workspace Layout — where the crates live.
- Contributing — sending the PR.