79. #[diagnostic::on_unimplemented] — Custom Error Messages for Your Traits
Trait errors are notoriously cryptic. #[diagnostic::on_unimplemented] lets you replace the compiler’s default “trait bound not satisfied” with a message that actually tells the user what went wrong.
The problem
You define a trait, someone forgets to implement it, and the compiler spits out a wall of generics and trait bounds that even experienced Rustaceans have to squint at:
| |
For your own code that’s fine — but if you’re writing a library, your users deserve better.
The fix
Annotate your trait with #[diagnostic::on_unimplemented] and the compiler will use your message instead:
| |
Now the error reads like documentation, not like a stack trace.
It works with generics too
The placeholders {Self} and {A} (for generic params) let you generate targeted messages:
| |
If someone tries to serialize a type for an unsupported format, they get a message that names both the type and the format — no guessing required.
Multiple notes
You can attach several note entries, and each one becomes a separate note in the compiler output:
| |
When to use it
This is a library-author tool. If you expose a public trait and expect users to implement it (or pass types that satisfy it), adding on_unimplemented is a small investment that saves your users real debugging time. Crates like bevy, axum, and diesel already use it to turn walls of trait errors into actionable guidance.
Stabilized in Rust 1.78, it’s part of the #[diagnostic] namespace — the compiler treats unrecognized diagnostic hints as soft warnings rather than hard errors, so it’s forward-compatible by design.