summary refs log tree commit diff
diff options
context:
space:
mode:
authorXiretza <xiretza@xiretza.xyz>2022-08-19 15:40:48 +0200
committerXiretza <xiretza@xiretza.xyz>2022-08-21 09:17:43 +0200
commit7f3a6fd7f6c04635f3d541201199f127f2a2e65e (patch)
tree4b9be1a4a7d5610f9ad2b58054724d900de1ee42
parentbd0d3f745d40c9de9c5dbc24dc7f8fb64ceb5575 (diff)
downloadrust-7f3a6fd7f6c04635f3d541201199f127f2a2e65e.tar.gz
rust-7f3a6fd7f6c04635f3d541201199f127f2a2e65e.zip
Replace #[lint/warning/error] with #[diag]
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs4
-rw-r--r--compiler/rustc_const_eval/src/errors.rs18
-rw-r--r--compiler/rustc_expand/src/errors.rs12
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs19
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs4
-rw-r--r--compiler/rustc_macros/src/lib.rs6
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs16
-rw-r--r--compiler/rustc_passes/src/errors.rs170
-rw-r--r--compiler/rustc_privacy/src/errors.rs14
-rw-r--r--compiler/rustc_typeck/src/errors.rs54
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.rs2
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs205
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr292
16 files changed, 443 insertions, 387 deletions
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 895723d44ff..8c9676e4bfa 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::Ty;
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::move_unsized, code = "E0161")]
+#[diag(borrowck::move_unsized, code = "E0161")]
 pub(crate) struct MoveUnsized<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -12,7 +12,7 @@ pub(crate) struct MoveUnsized<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::higher_ranked_lifetime_error)]
+#[diag(borrowck::higher_ranked_lifetime_error)]
 pub(crate) struct HigherRankedLifetimeError {
     #[subdiagnostic]
     pub cause: Option<HigherRankedErrorCause>,
@@ -29,14 +29,14 @@ pub(crate) enum HigherRankedErrorCause {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::higher_ranked_subtype_error)]
+#[diag(borrowck::higher_ranked_subtype_error)]
 pub(crate) struct HigherRankedSubtypeError {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::generic_does_not_live_long_enough)]
+#[diag(borrowck::generic_does_not_live_long_enough)]
 pub(crate) struct GenericDoesNotLiveLongEnough {
     pub kind: String,
     #[primary_span]
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index aa355150b4f..9046bf13059 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -36,7 +36,7 @@ pub fn expand_cfg(
 }
 
 #[derive(SessionDiagnostic)]
-#[error(builtin_macros::requires_cfg_pattern)]
+#[diag(builtin_macros::requires_cfg_pattern)]
 struct RequiresCfgPattern {
     #[primary_span]
     #[label]
@@ -44,7 +44,7 @@ struct RequiresCfgPattern {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(builtin_macros::expected_one_cfg_pattern)]
+#[diag(builtin_macros::expected_one_cfg_pattern)]
 struct OneCfgPattern {
     #[primary_span]
     span: Span,
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index a463fe7b970..01619dee0e4 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_macros::SessionDiagnostic;
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::unstable_in_stable)]
+#[diag(const_eval::unstable_in_stable)]
 pub(crate) struct UnstableInStable {
     pub gate: String,
     #[primary_span]
@@ -22,14 +22,14 @@ pub(crate) struct UnstableInStable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::thread_local_access, code = "E0625")]
+#[diag(const_eval::thread_local_access, code = "E0625")]
 pub(crate) struct NonConstOpErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::static_access, code = "E0013")]
+#[diag(const_eval::static_access, code = "E0013")]
 #[help]
 pub(crate) struct StaticAccessErr {
     #[primary_span]
@@ -41,7 +41,7 @@ pub(crate) struct StaticAccessErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::raw_ptr_to_int)]
+#[diag(const_eval::raw_ptr_to_int)]
 #[note]
 #[note(const_eval::note2)]
 pub(crate) struct RawPtrToIntErr {
@@ -50,7 +50,7 @@ pub(crate) struct RawPtrToIntErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::raw_ptr_comparison)]
+#[diag(const_eval::raw_ptr_comparison)]
 #[note]
 pub(crate) struct RawPtrComparisonErr {
     #[primary_span]
@@ -58,14 +58,14 @@ pub(crate) struct RawPtrComparisonErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::panic_non_str)]
+#[diag(const_eval::panic_non_str)]
 pub(crate) struct PanicNonStrErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::mut_deref, code = "E0658")]
+#[diag(const_eval::mut_deref, code = "E0658")]
 pub(crate) struct MutDerefErr {
     #[primary_span]
     pub span: Span,
@@ -73,7 +73,7 @@ pub(crate) struct MutDerefErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::transient_mut_borrow, code = "E0658")]
+#[diag(const_eval::transient_mut_borrow, code = "E0658")]
 pub(crate) struct TransientMutBorrowErr {
     #[primary_span]
     pub span: Span,
@@ -81,7 +81,7 @@ pub(crate) struct TransientMutBorrowErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::transient_mut_borrow_raw, code = "E0658")]
+#[diag(const_eval::transient_mut_borrow_raw, code = "E0658")]
 pub(crate) struct TransientMutBorrowErrRaw {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 0d7e137c7dd..0feae0debd2 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -3,28 +3,28 @@ use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(expand::expr_repeat_no_syntax_vars)]
+#[diag(expand::expr_repeat_no_syntax_vars)]
 pub(crate) struct NoSyntaxVarsExprRepeat {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(expand::must_repeat_once)]
+#[diag(expand::must_repeat_once)]
 pub(crate) struct MustRepeatOnce {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(expand::count_repetition_misplaced)]
+#[diag(expand::count_repetition_misplaced)]
 pub(crate) struct CountRepetitionMisplaced {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(expand::meta_var_expr_unrecognized_var)]
+#[diag(expand::meta_var_expr_unrecognized_var)]
 pub(crate) struct MetaVarExprUnrecognizedVar {
     #[primary_span]
     pub span: Span,
@@ -32,7 +32,7 @@ pub(crate) struct MetaVarExprUnrecognizedVar {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(expand::var_still_repeating)]
+#[diag(expand::var_still_repeating)]
 pub(crate) struct VarStillRepeating {
     #[primary_span]
     pub span: Span,
@@ -40,7 +40,7 @@ pub(crate) struct VarStillRepeating {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(expand::meta_var_dif_seq_matchers)]
+#[diag(expand::meta_var_dif_seq_matchers)]
 pub(crate) struct MetaVarsDifSeqMatchers {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index e00d0b7d0d8..014cf88389e 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -265,7 +265,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(interface::ferris_identifier)]
+#[diag(interface::ferris_identifier)]
 struct FerrisIdentifier {
     #[primary_span]
     spans: Vec<Span>,
@@ -274,7 +274,7 @@ struct FerrisIdentifier {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(interface::emoji_identifier)]
+#[diag(interface::emoji_identifier)]
 struct EmojiIdentifier {
     #[primary_span]
     spans: Vec<Span>,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index cafd2c6e679..484e541afc5 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1546,7 +1546,7 @@ impl InvalidAtomicOrdering {
 
         if matches!(fail_ordering, sym::Release | sym::AcqRel) {
             #[derive(LintDiagnostic)]
-            #[lint(lint::atomic_ordering_invalid)]
+            #[diag(lint::atomic_ordering_invalid)]
             #[help]
             struct InvalidAtomicOrderingDiag {
                 method: Symbol,
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 31ea6bb779e..9df9fa4e9bf 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -141,7 +141,7 @@ impl DiagnosticDeriveBuilder {
         let name = name.as_str();
         let meta = attr.parse_meta()?;
 
-        let is_diag = matches!(name, "error" | "warning" | "lint" | "diag");
+        let is_diag = name == "diag";
 
         let nested = match meta {
             // Most attributes are lists, like `#[diag(..)]` for most cases or
@@ -163,20 +163,9 @@ impl DiagnosticDeriveBuilder {
         // Check the kind before doing any further processing so that there aren't misleading
         // "no kind specified" errors if there are failures later.
         match name {
-            "error" | "warning" => {
-                if self.kind == DiagnosticDeriveKind::LintDiagnostic {
-                    span_err(span, "only `#[lint(..)]` is supported")
-                        .help("use the `#[lint(...)]` attribute to create a lint")
-                        .emit();
-                }
-            }
-            "lint" => {
-                if self.kind == DiagnosticDeriveKind::SessionDiagnostic {
-                    span_err(span, "only `#[error(..)]` and `#[warning(..)]` are supported")
-                        .help("use the `#[error(...)]` attribute to create a error")
-                        .emit();
-                }
-            }
+            "error" | "warning" | "lint" => throw_invalid_attr!(attr, &meta, |diag| {
+                diag.help("`error`, `warning` and `lint` have been replaced by `diag`")
+            }),
             "diag" | "help" | "note" | "warn_" => (),
             _ => throw_invalid_attr!(attr, &meta, |diag| {
                 diag.help("only `diag`, `help`, `note` and `warn_` are valid attributes")
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 733454cb2a7..2ff21e18ff8 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -23,7 +23,7 @@ use synstructure::Structure;
 /// # extern crate rust_middle;
 /// # use rustc_middle::ty::Ty;
 /// #[derive(SessionDiagnostic)]
-/// #[error(borrowck::move_out_of_borrow, code = "E0505")]
+/// #[diag(borrowck::move_out_of_borrow, code = "E0505")]
 /// pub struct MoveOutOfBorrowError<'tcx> {
 ///     pub name: Ident,
 ///     pub ty: Ty<'tcx>,
@@ -67,7 +67,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
 ///
 /// ```ignore (rust)
 /// #[derive(LintDiagnostic)]
-/// #[lint(lint::atomic_ordering_invalid_fail_success)]
+/// #[diag(lint::atomic_ordering_invalid_fail_success)]
 /// pub struct AtomicOrderingInvalidLint {
 ///     method: Symbol,
 ///     success_ordering: Symbol,
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index fe4ff2fb6aa..87d7ab6ed51 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -129,9 +129,6 @@ decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
 decl_derive!(
     [SessionDiagnostic, attributes(
         // struct attributes
-        warning,
-        error,
-        lint,
         diag,
         help,
         note,
@@ -149,9 +146,6 @@ decl_derive!(
 decl_derive!(
     [LintDiagnostic, attributes(
         // struct attributes
-        warning,
-        error,
-        lint,
         diag,
         help,
         note,
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 744ec7e6114..7beec270e3b 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -244,7 +244,7 @@ impl MultiSugg {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::maybe_report_ambiguous_plus)]
+#[diag(parser::maybe_report_ambiguous_plus)]
 struct AmbiguousPlus {
     pub sum_ty: String,
     #[primary_span]
@@ -253,7 +253,7 @@ struct AmbiguousPlus {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
+#[diag(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
 struct BadTypePlus {
     pub ty: String,
     #[primary_span]
@@ -287,7 +287,7 @@ pub enum BadTypePlusSub {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::maybe_recover_from_bad_qpath_stage_2)]
+#[diag(parser::maybe_recover_from_bad_qpath_stage_2)]
 struct BadQPathStage2 {
     #[primary_span]
     #[suggestion(applicability = "maybe-incorrect")]
@@ -296,7 +296,7 @@ struct BadQPathStage2 {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::incorrect_semicolon)]
+#[diag(parser::incorrect_semicolon)]
 struct IncorrectSemicolon<'a> {
     #[primary_span]
     #[suggestion_short(applicability = "machine-applicable")]
@@ -307,7 +307,7 @@ struct IncorrectSemicolon<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::incorrect_use_of_await)]
+#[diag(parser::incorrect_use_of_await)]
 struct IncorrectUseOfAwait {
     #[primary_span]
     #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")]
@@ -315,7 +315,7 @@ struct IncorrectUseOfAwait {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::incorrect_use_of_await)]
+#[diag(parser::incorrect_use_of_await)]
 struct IncorrectAwait {
     #[primary_span]
     span: Span,
@@ -326,7 +326,7 @@ struct IncorrectAwait {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::in_in_typo)]
+#[diag(parser::in_in_typo)]
 struct InInTypo {
     #[primary_span]
     span: Span,
@@ -335,7 +335,7 @@ struct InInTypo {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::invalid_variable_declaration)]
+#[diag(parser::invalid_variable_declaration)]
 pub struct InvalidVariableDeclaration {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index f41ff2c9b17..383982013d9 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -3,37 +3,37 @@ use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(LintDiagnostic)]
-#[lint(passes::outer_crate_level_attr)]
+#[diag(passes::outer_crate_level_attr)]
 pub struct OuterCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inner_crate_level_attr)]
+#[diag(passes::inner_crate_level_attr)]
 pub struct InnerCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::ignored_attr_with_macro)]
+#[diag(passes::ignored_attr_with_macro)]
 pub struct IgnoredAttrWithMacro<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::ignored_attr)]
+#[diag(passes::ignored_attr)]
 pub struct IgnoredAttr<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inline_ignored_function_prototype)]
+#[diag(passes::inline_ignored_function_prototype)]
 pub struct IgnoredInlineAttrFnProto;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inline_ignored_constants)]
+#[diag(passes::inline_ignored_constants)]
 #[warn_]
 #[note]
 pub struct IgnoredInlineAttrConstants;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::inline_not_fn_or_closure, code = "E0518")]
+#[diag(passes::inline_not_fn_or_closure, code = "E0518")]
 pub struct InlineNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
@@ -42,19 +42,19 @@ pub struct InlineNotFnOrClosure {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_ignored_function_prototype)]
+#[diag(passes::no_coverage_ignored_function_prototype)]
 pub struct IgnoredNoCoverageFnProto;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_propagate)]
+#[diag(passes::no_coverage_propagate)]
 pub struct IgnoredNoCoveragePropagate;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_fn_defn)]
+#[diag(passes::no_coverage_fn_defn)]
 pub struct IgnoredNoCoverageFnDefn;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::no_coverage_not_coverable, code = "E0788")]
+#[diag(passes::no_coverage_not_coverable, code = "E0788")]
 pub struct IgnoredNoCoverageNotCoverable {
     #[primary_span]
     pub attr_span: Span,
@@ -63,7 +63,7 @@ pub struct IgnoredNoCoverageNotCoverable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_fn)]
+#[diag(passes::should_be_applied_to_fn)]
 pub struct AttrShouldBeAppliedToFn {
     #[primary_span]
     pub attr_span: Span,
@@ -72,14 +72,14 @@ pub struct AttrShouldBeAppliedToFn {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::naked_tracked_caller, code = "E0736")]
+#[diag(passes::naked_tracked_caller, code = "E0736")]
 pub struct NakedTrackedCaller {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_fn, code = "E0739")]
+#[diag(passes::should_be_applied_to_fn, code = "E0739")]
 pub struct TrackedCallerWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -88,7 +88,7 @@ pub struct TrackedCallerWrongLocation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_struct_enum, code = "E0701")]
+#[diag(passes::should_be_applied_to_struct_enum, code = "E0701")]
 pub struct NonExhaustiveWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -97,7 +97,7 @@ pub struct NonExhaustiveWrongLocation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_trait)]
+#[diag(passes::should_be_applied_to_trait)]
 pub struct AttrShouldBeAppliedToTrait {
     #[primary_span]
     pub attr_span: Span,
@@ -106,11 +106,11 @@ pub struct AttrShouldBeAppliedToTrait {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::target_feature_on_statement)]
+#[diag(passes::target_feature_on_statement)]
 pub struct TargetFeatureOnStatement;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_static)]
+#[diag(passes::should_be_applied_to_static)]
 pub struct AttrShouldBeAppliedToStatic {
     #[primary_span]
     pub attr_span: Span,
@@ -119,7 +119,7 @@ pub struct AttrShouldBeAppliedToStatic {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_expect_str)]
+#[diag(passes::doc_expect_str)]
 pub struct DocExpectStr<'a> {
     #[primary_span]
     pub attr_span: Span,
@@ -127,7 +127,7 @@ pub struct DocExpectStr<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_empty)]
+#[diag(passes::doc_alias_empty)]
 pub struct DocAliasEmpty<'a> {
     #[primary_span]
     pub span: Span,
@@ -135,7 +135,7 @@ pub struct DocAliasEmpty<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_bad_char)]
+#[diag(passes::doc_alias_bad_char)]
 pub struct DocAliasBadChar<'a> {
     #[primary_span]
     pub span: Span,
@@ -144,7 +144,7 @@ pub struct DocAliasBadChar<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_start_end)]
+#[diag(passes::doc_alias_start_end)]
 pub struct DocAliasStartEnd<'a> {
     #[primary_span]
     pub span: Span,
@@ -152,7 +152,7 @@ pub struct DocAliasStartEnd<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_bad_location)]
+#[diag(passes::doc_alias_bad_location)]
 pub struct DocAliasBadLocation<'a> {
     #[primary_span]
     pub span: Span,
@@ -161,7 +161,7 @@ pub struct DocAliasBadLocation<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_not_an_alias)]
+#[diag(passes::doc_alias_not_an_alias)]
 pub struct DocAliasNotAnAlias<'a> {
     #[primary_span]
     pub span: Span,
@@ -169,42 +169,42 @@ pub struct DocAliasNotAnAlias<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_alias_duplicated)]
+#[diag(passes::doc_alias_duplicated)]
 pub struct DocAliasDuplicated {
     #[label]
     pub first_defn: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_not_string_literal)]
+#[diag(passes::doc_alias_not_string_literal)]
 pub struct DocAliasNotStringLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_malformed)]
+#[diag(passes::doc_alias_malformed)]
 pub struct DocAliasMalformed {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_empty_mod)]
+#[diag(passes::doc_keyword_empty_mod)]
 pub struct DocKeywordEmptyMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_not_mod)]
+#[diag(passes::doc_keyword_not_mod)]
 pub struct DocKeywordNotMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_invalid_ident)]
+#[diag(passes::doc_keyword_invalid_ident)]
 pub struct DocKeywordInvalidIdent {
     #[primary_span]
     pub span: Span,
@@ -212,21 +212,21 @@ pub struct DocKeywordInvalidIdent {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_fake_variadic_not_valid)]
+#[diag(passes::doc_fake_variadic_not_valid)]
 pub struct DocFakeVariadicNotValid {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_only_impl)]
+#[diag(passes::doc_keyword_only_impl)]
 pub struct DocKeywordOnlyImpl {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_inline_conflict)]
+#[diag(passes::doc_inline_conflict)]
 #[help]
 pub struct DocKeywordConflict {
     #[primary_span]
@@ -234,7 +234,7 @@ pub struct DocKeywordConflict {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_inline_only_use)]
+#[diag(passes::doc_inline_only_use)]
 #[note]
 pub struct DocInlineOnlyUse {
     #[label]
@@ -244,7 +244,7 @@ pub struct DocInlineOnlyUse {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_attr_not_crate_level)]
+#[diag(passes::doc_attr_not_crate_level)]
 pub struct DocAttrNotCrateLevel<'a> {
     #[primary_span]
     pub span: Span,
@@ -252,27 +252,27 @@ pub struct DocAttrNotCrateLevel<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown)]
+#[diag(passes::doc_test_unknown)]
 pub struct DocTestUnknown {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_takes_list)]
+#[diag(passes::doc_test_takes_list)]
 pub struct DocTestTakesList;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_primitive)]
+#[diag(passes::doc_primitive)]
 pub struct DocPrimitive;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_any)]
+#[diag(passes::doc_test_unknown_any)]
 pub struct DocTestUnknownAny {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_spotlight)]
+#[diag(passes::doc_test_unknown_spotlight)]
 #[note]
 #[note(passes::no_op_note)]
 pub struct DocTestUnknownSpotlight {
@@ -282,7 +282,7 @@ pub struct DocTestUnknownSpotlight {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_include)]
+#[diag(passes::doc_test_unknown_include)]
 pub struct DocTestUnknownInclude {
     pub path: String,
     pub value: String,
@@ -292,11 +292,11 @@ pub struct DocTestUnknownInclude {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_invalid)]
+#[diag(passes::doc_invalid)]
 pub struct DocInvalid;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::pass_by_value)]
+#[diag(passes::pass_by_value)]
 pub struct PassByValue {
     #[primary_span]
     pub attr_span: Span,
@@ -305,7 +305,7 @@ pub struct PassByValue {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::allow_incoherent_impl)]
+#[diag(passes::allow_incoherent_impl)]
 pub struct AllowIncoherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -314,7 +314,7 @@ pub struct AllowIncoherentImpl {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::has_incoherent_inherent_impl)]
+#[diag(passes::has_incoherent_inherent_impl)]
 pub struct HasIncoherentInherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -323,21 +323,21 @@ pub struct HasIncoherentInherentImpl {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::must_use_async)]
+#[diag(passes::must_use_async)]
 pub struct MustUseAsync {
     #[label]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::must_use_no_effect)]
+#[diag(passes::must_use_no_effect)]
 pub struct MustUseNoEffect {
     pub article: &'static str,
     pub target: rustc_hir::Target,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::must_not_suspend)]
+#[diag(passes::must_not_suspend)]
 pub struct MustNotSuspend {
     #[primary_span]
     pub attr_span: Span,
@@ -346,7 +346,7 @@ pub struct MustNotSuspend {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::cold)]
+#[diag(passes::cold)]
 #[warn_]
 pub struct Cold {
     #[label]
@@ -354,7 +354,7 @@ pub struct Cold {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link)]
+#[diag(passes::link)]
 #[warn_]
 pub struct Link {
     #[label]
@@ -362,7 +362,7 @@ pub struct Link {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link_name)]
+#[diag(passes::link_name)]
 #[warn_]
 pub struct LinkName<'a> {
     #[help]
@@ -373,7 +373,7 @@ pub struct LinkName<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::no_link)]
+#[diag(passes::no_link)]
 pub struct NoLink {
     #[primary_span]
     pub attr_span: Span,
@@ -382,7 +382,7 @@ pub struct NoLink {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::export_name)]
+#[diag(passes::export_name)]
 pub struct ExportName {
     #[primary_span]
     pub attr_span: Span,
@@ -391,7 +391,7 @@ pub struct ExportName {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_layout_scalar_valid_range_not_struct)]
+#[diag(passes::rustc_layout_scalar_valid_range_not_struct)]
 pub struct RustcLayoutScalarValidRangeNotStruct {
     #[primary_span]
     pub attr_span: Span,
@@ -400,14 +400,14 @@ pub struct RustcLayoutScalarValidRangeNotStruct {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_layout_scalar_valid_range_arg)]
+#[diag(passes::rustc_layout_scalar_valid_range_arg)]
 pub struct RustcLayoutScalarValidRangeArg {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_only)]
+#[diag(passes::rustc_legacy_const_generics_only)]
 pub struct RustcLegacyConstGenericsOnly {
     #[primary_span]
     pub attr_span: Span,
@@ -416,7 +416,7 @@ pub struct RustcLegacyConstGenericsOnly {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index)]
+#[diag(passes::rustc_legacy_const_generics_index)]
 pub struct RustcLegacyConstGenericsIndex {
     #[primary_span]
     pub attr_span: Span,
@@ -425,7 +425,7 @@ pub struct RustcLegacyConstGenericsIndex {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index_exceed)]
+#[diag(passes::rustc_legacy_const_generics_index_exceed)]
 pub struct RustcLegacyConstGenericsIndexExceed {
     #[primary_span]
     #[label]
@@ -434,21 +434,21 @@ pub struct RustcLegacyConstGenericsIndexExceed {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index_negative)]
+#[diag(passes::rustc_legacy_const_generics_index_negative)]
 pub struct RustcLegacyConstGenericsIndexNegative {
     #[primary_span]
     pub invalid_args: Vec<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_dirty_clean)]
+#[diag(passes::rustc_dirty_clean)]
 pub struct RustcDirtyClean {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link_section)]
+#[diag(passes::link_section)]
 #[warn_]
 pub struct LinkSection {
     #[label]
@@ -456,7 +456,7 @@ pub struct LinkSection {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_mangle_foreign)]
+#[diag(passes::no_mangle_foreign)]
 #[warn_]
 #[note]
 pub struct NoMangleForeign {
@@ -468,7 +468,7 @@ pub struct NoMangleForeign {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_mangle)]
+#[diag(passes::no_mangle)]
 #[warn_]
 pub struct NoMangle {
     #[label]
@@ -476,32 +476,32 @@ pub struct NoMangle {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::repr_ident, code = "E0565")]
+#[diag(passes::repr_ident, code = "E0565")]
 pub struct ReprIdent {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::repr_conflicting, code = "E0566")]
+#[diag(passes::repr_conflicting, code = "E0566")]
 pub struct ReprConflicting;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::used_static)]
+#[diag(passes::used_static)]
 pub struct UsedStatic {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::used_compiler_linker)]
+#[diag(passes::used_compiler_linker)]
 pub struct UsedCompilerLinker {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::allow_internal_unstable)]
+#[diag(passes::allow_internal_unstable)]
 pub struct AllowInternalUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -510,14 +510,14 @@ pub struct AllowInternalUnstable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::debug_visualizer_placement)]
+#[diag(passes::debug_visualizer_placement)]
 pub struct DebugVisualizerPlacement {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::debug_visualizer_invalid)]
+#[diag(passes::debug_visualizer_invalid)]
 #[note(passes::note_1)]
 #[note(passes::note_2)]
 #[note(passes::note_3)]
@@ -527,7 +527,7 @@ pub struct DebugVisualizerInvalid {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_allow_const_fn_unstable)]
+#[diag(passes::rustc_allow_const_fn_unstable)]
 pub struct RustcAllowConstFnUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -536,7 +536,7 @@ pub struct RustcAllowConstFnUnstable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_std_internal_symbol)]
+#[diag(passes::rustc_std_internal_symbol)]
 pub struct RustcStdInternalSymbol {
     #[primary_span]
     pub attr_span: Span,
@@ -545,42 +545,42 @@ pub struct RustcStdInternalSymbol {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::const_trait)]
+#[diag(passes::const_trait)]
 pub struct ConstTrait {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::link_ordinal)]
+#[diag(passes::link_ordinal)]
 pub struct LinkOrdinal {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::stability_promotable)]
+#[diag(passes::stability_promotable)]
 pub struct StabilityPromotable {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::deprecated)]
+#[diag(passes::deprecated)]
 pub struct Deprecated;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::macro_use)]
+#[diag(passes::macro_use)]
 pub struct MacroUse {
     pub name: Symbol,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::macro_export)]
+#[diag(passes::macro_export)]
 pub struct MacroExport;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::plugin_registrar)]
+#[diag(passes::plugin_registrar)]
 pub struct PluginRegistrar;
 
 #[derive(SessionSubdiagnostic)]
@@ -594,7 +594,7 @@ pub enum UnusedNote {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::unused)]
+#[diag(passes::unused)]
 pub struct Unused {
     #[suggestion(applicability = "machine-applicable")]
     pub attr_span: Span,
@@ -603,7 +603,7 @@ pub struct Unused {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::non_exported_macro_invalid_attrs, code = "E0518")]
+#[diag(passes::non_exported_macro_invalid_attrs, code = "E0518")]
 pub struct NonExportedMacroInvalidAttrs {
     #[primary_span]
     #[label]
@@ -611,7 +611,7 @@ pub struct NonExportedMacroInvalidAttrs {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::unused_duplicate)]
+#[diag(passes::unused_duplicate)]
 pub struct UnusedDuplicate {
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub this: Span,
@@ -622,7 +622,7 @@ pub struct UnusedDuplicate {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::unused_multiple)]
+#[diag(passes::unused_multiple)]
 pub struct UnusedMultiple {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -633,7 +633,7 @@ pub struct UnusedMultiple {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_lint_opt_ty)]
+#[diag(passes::rustc_lint_opt_ty)]
 pub struct RustcLintOptTy {
     #[primary_span]
     pub attr_span: Span,
@@ -642,7 +642,7 @@ pub struct RustcLintOptTy {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_lint_opt_deny_field_access)]
+#[diag(passes::rustc_lint_opt_deny_field_access)]
 pub struct RustcLintOptDenyFieldAccess {
     #[primary_span]
     pub attr_span: Span,
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index aca7d770f34..1e423ddb710 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(SessionDiagnostic)]
-#[error(privacy::field_is_private, code = "E0451")]
+#[diag(privacy::field_is_private, code = "E0451")]
 pub struct FieldIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -30,7 +30,7 @@ pub enum FieldIsPrivateLabel {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(privacy::item_is_private)]
+#[diag(privacy::item_is_private)]
 pub struct ItemIsPrivate<'a> {
     #[primary_span]
     #[label]
@@ -40,7 +40,7 @@ pub struct ItemIsPrivate<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(privacy::unnamed_item_is_private)]
+#[diag(privacy::unnamed_item_is_private)]
 pub struct UnnamedItemIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -49,7 +49,7 @@ pub struct UnnamedItemIsPrivate {
 
 // Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
 #[derive(SessionDiagnostic)]
-#[error(privacy::in_public_interface, code = "E0445")]
+#[diag(privacy::in_public_interface, code = "E0445")]
 pub struct InPublicInterfaceTraits<'a> {
     #[primary_span]
     #[label]
@@ -63,7 +63,7 @@ pub struct InPublicInterfaceTraits<'a> {
 
 // Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
 #[derive(SessionDiagnostic)]
-#[error(privacy::in_public_interface, code = "E0446")]
+#[diag(privacy::in_public_interface, code = "E0446")]
 pub struct InPublicInterface<'a> {
     #[primary_span]
     #[label]
@@ -76,7 +76,7 @@ pub struct InPublicInterface<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(privacy::from_private_dep_in_public_interface)]
+#[diag(privacy::from_private_dep_in_public_interface)]
 pub struct FromPrivateDependencyInPublicInterface<'a> {
     pub kind: &'a str,
     pub descr: DiagnosticArgFromDisplay<'a>,
@@ -84,7 +84,7 @@ pub struct FromPrivateDependencyInPublicInterface<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(privacy::private_in_public_lint)]
+#[diag(privacy::private_in_public_lint)]
 pub struct PrivateInPublicLint<'a> {
     pub vis_descr: &'static str,
     pub kind: &'a str,
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs
index 8b1cb8d1c93..2214fc2ced8 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_typeck/src/errors.rs
@@ -6,7 +6,7 @@ use rustc_session::{parse::ParseSess, SessionDiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::field_multiply_specified_in_initializer, code = "E0062")]
+#[diag(typeck::field_multiply_specified_in_initializer, code = "E0062")]
 pub struct FieldMultiplySpecifiedInInitializer {
     #[primary_span]
     #[label]
@@ -17,7 +17,7 @@ pub struct FieldMultiplySpecifiedInInitializer {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::unrecognized_atomic_operation, code = "E0092")]
+#[diag(typeck::unrecognized_atomic_operation, code = "E0092")]
 pub struct UnrecognizedAtomicOperation<'a> {
     #[primary_span]
     #[label]
@@ -26,7 +26,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
+#[diag(typeck::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
 pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
     #[primary_span]
     #[label]
@@ -37,7 +37,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::unrecognized_intrinsic_function, code = "E0093")]
+#[diag(typeck::unrecognized_intrinsic_function, code = "E0093")]
 pub struct UnrecognizedIntrinsicFunction {
     #[primary_span]
     #[label]
@@ -46,7 +46,7 @@ pub struct UnrecognizedIntrinsicFunction {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
+#[diag(typeck::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
 pub struct LifetimesOrBoundsMismatchOnTrait {
     #[primary_span]
     #[label]
@@ -58,7 +58,7 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::drop_impl_on_wrong_item, code = "E0120")]
+#[diag(typeck::drop_impl_on_wrong_item, code = "E0120")]
 pub struct DropImplOnWrongItem {
     #[primary_span]
     #[label]
@@ -66,7 +66,7 @@ pub struct DropImplOnWrongItem {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::field_already_declared, code = "E0124")]
+#[diag(typeck::field_already_declared, code = "E0124")]
 pub struct FieldAlreadyDeclared {
     pub field_name: Ident,
     #[primary_span]
@@ -77,7 +77,7 @@ pub struct FieldAlreadyDeclared {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::copy_impl_on_type_with_dtor, code = "E0184")]
+#[diag(typeck::copy_impl_on_type_with_dtor, code = "E0184")]
 pub struct CopyImplOnTypeWithDtor {
     #[primary_span]
     #[label]
@@ -85,14 +85,14 @@ pub struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::multiple_relaxed_default_bounds, code = "E0203")]
+#[diag(typeck::multiple_relaxed_default_bounds, code = "E0203")]
 pub struct MultipleRelaxedDefaultBounds {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::copy_impl_on_non_adt, code = "E0206")]
+#[diag(typeck::copy_impl_on_non_adt, code = "E0206")]
 pub struct CopyImplOnNonAdt {
     #[primary_span]
     #[label]
@@ -100,7 +100,7 @@ pub struct CopyImplOnNonAdt {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::trait_object_declared_with_no_traits, code = "E0224")]
+#[diag(typeck::trait_object_declared_with_no_traits, code = "E0224")]
 pub struct TraitObjectDeclaredWithNoTraits {
     #[primary_span]
     pub span: Span,
@@ -109,14 +109,14 @@ pub struct TraitObjectDeclaredWithNoTraits {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0227")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0227")]
 pub struct AmbiguousLifetimeBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::assoc_type_binding_not_allowed, code = "E0229")]
+#[diag(typeck::assoc_type_binding_not_allowed, code = "E0229")]
 pub struct AssocTypeBindingNotAllowed {
     #[primary_span]
     #[label]
@@ -124,14 +124,14 @@ pub struct AssocTypeBindingNotAllowed {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::functional_record_update_on_non_struct, code = "E0436")]
+#[diag(typeck::functional_record_update_on_non_struct, code = "E0436")]
 pub struct FunctionalRecordUpdateOnNonStruct {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::typeof_reserved_keyword_used, code = "E0516")]
+#[diag(typeck::typeof_reserved_keyword_used, code = "E0516")]
 pub struct TypeofReservedKeywordUsed<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -142,7 +142,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::return_stmt_outside_of_fn_body, code = "E0572")]
+#[diag(typeck::return_stmt_outside_of_fn_body, code = "E0572")]
 pub struct ReturnStmtOutsideOfFnBody {
     #[primary_span]
     pub span: Span,
@@ -153,14 +153,14 @@ pub struct ReturnStmtOutsideOfFnBody {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::yield_expr_outside_of_generator, code = "E0627")]
+#[diag(typeck::yield_expr_outside_of_generator, code = "E0627")]
 pub struct YieldExprOutsideOfGenerator {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::struct_expr_non_exhaustive, code = "E0639")]
+#[diag(typeck::struct_expr_non_exhaustive, code = "E0639")]
 pub struct StructExprNonExhaustive {
     #[primary_span]
     pub span: Span,
@@ -168,14 +168,14 @@ pub struct StructExprNonExhaustive {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::method_call_on_unknown_type, code = "E0699")]
+#[diag(typeck::method_call_on_unknown_type, code = "E0699")]
 pub struct MethodCallOnUnknownType {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::value_of_associated_struct_already_specified, code = "E0719")]
+#[diag(typeck::value_of_associated_struct_already_specified, code = "E0719")]
 pub struct ValueOfAssociatedStructAlreadySpecified {
     #[primary_span]
     #[label]
@@ -187,7 +187,7 @@ pub struct ValueOfAssociatedStructAlreadySpecified {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::address_of_temporary_taken, code = "E0745")]
+#[diag(typeck::address_of_temporary_taken, code = "E0745")]
 pub struct AddressOfTemporaryTaken {
     #[primary_span]
     #[label]
@@ -233,7 +233,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::unconstrained_opaque_type)]
+#[diag(typeck::unconstrained_opaque_type)]
 #[note]
 pub struct UnconstrainedOpaqueType {
     #[primary_span]
@@ -309,7 +309,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::manual_implementation, code = "E0183")]
+#[diag(typeck::manual_implementation, code = "E0183")]
 #[help]
 pub struct ManualImplementation {
     #[primary_span]
@@ -319,21 +319,21 @@ pub struct ManualImplementation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::substs_on_overridden_impl)]
+#[diag(typeck::substs_on_overridden_impl)]
 pub struct SubstsOnOverriddenImpl {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(typeck::unused_extern_crate)]
+#[diag(typeck::unused_extern_crate)]
 pub struct UnusedExternCrate {
     #[suggestion(applicability = "machine-applicable", code = "")]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(typeck::extern_crate_not_idiomatic)]
+#[diag(typeck::extern_crate_not_idiomatic)]
 pub struct ExternCrateNotIdiomatic {
     #[suggestion_short(applicability = "machine-applicable", code = "{suggestion_code}")]
     pub span: Span,
@@ -342,7 +342,7 @@ pub struct ExternCrateNotIdiomatic {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::expected_used_symbol)]
+#[diag(typeck::expected_used_symbol)]
 pub struct ExpectedUsedSymbol {
     #[primary_span]
     pub span: Span,
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
index d6f63d44ba6..33192433bbf 100644
--- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
@@ -16,7 +16,7 @@ use rustc_session::{parse::ParseSess, SessionDiagnostic};
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(parser::expect_path)]
+#[diag(parser::expect_path)]
 struct DeriveSessionDiagnostic {
     #[primary_span]
     span: Span,
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 842fdee9221..aaa8caa64f3 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -28,15 +28,15 @@ use rustc_errors::{Applicability, MultiSpan};
 extern crate rustc_session;
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct Hello {}
 
 #[derive(SessionDiagnostic)]
-#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct HelloWarn {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 //~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs
 enum SessionDiagnosticOnEnum {
     Foo,
@@ -44,9 +44,9 @@ enum SessionDiagnosticOnEnum {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[error = "E0123"]
-//~^ ERROR `#[error = ...]` is not a valid attribute
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag = "E0123"]
+//~^ ERROR `#[diag = ...]` is not a valid attribute
 struct WrongStructAttrStyle {}
 
 #[derive(SessionDiagnostic)]
@@ -57,41 +57,41 @@ struct WrongStructAttrStyle {}
 struct InvalidStructAttr {}
 
 #[derive(SessionDiagnostic)]
-#[error("E0123")]
-//~^ ERROR `#[error("...")]` is not a valid attribute
+#[diag("E0123")]
+//~^ ERROR `#[diag("...")]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidLitNestedAttr {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense, code = "E0123")]
+#[diag(nonsense, code = "E0123")]
 //~^ ERROR cannot find value `nonsense` in module `rustc_errors::fluent`
 struct InvalidNestedStructAttr {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense("foo"), code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(nonsense(...))]` is not a valid attribute
+#[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(nonsense(...))]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr1 {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense = "...", code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
+#[diag(nonsense = "...", code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr2 {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense = 4, code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
+#[diag(nonsense = 4, code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr3 {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(slug = ...)]` is not a valid attribute
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute
 struct InvalidNestedStructAttr4 {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct WrongPlaceField {
     #[suggestion = "bar"]
     //~^ ERROR `#[suggestion = ...]` is not a valid attribute
@@ -99,43 +99,36 @@ struct WrongPlaceField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
-struct ErrorSpecifiedTwice {}
+struct DiagSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-//~^ ERROR specified multiple times
-//~^^ ERROR specified multiple times
-struct WarnSpecifiedAfterError {}
-
-#[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
 //~^ ERROR specified multiple times
 struct CodeSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
-//~^ ERROR `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
+#[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
+//~^ ERROR `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
 struct SlugSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
 struct KindNotProvided {} //~ ERROR diagnostic slug not specified
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0456")]
+#[diag(code = "E0456")]
 //~^ ERROR diagnostic slug not specified
 struct SlugNotProvided {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound)]
+#[diag(typeck::ambiguous_lifetime_bound)]
 struct CodeNotProvided {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct MessageWrongType {
     #[primary_span]
     //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -143,7 +136,7 @@ struct MessageWrongType {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct InvalidPathFieldAttr {
     #[nonsense]
     //~^ ERROR `#[nonsense]` is not a valid attribute
@@ -152,7 +145,7 @@ struct InvalidPathFieldAttr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithField {
     name: String,
     #[label(typeck::label)]
@@ -160,7 +153,7 @@ struct ErrorWithField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithMessageAppliedToField {
     #[label(typeck::label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -168,7 +161,7 @@ struct ErrorWithMessageAppliedToField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNonexistentField {
     #[suggestion(typeck::suggestion, code = "{name}")]
     //~^ ERROR `name` doesn't refer to a field on this type
@@ -177,7 +170,7 @@ struct ErrorWithNonexistentField {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR invalid format string: expected `'}'`
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorMissingClosingBrace {
     #[suggestion(typeck::suggestion, code = "{name")]
     suggestion: (Span, Applicability),
@@ -187,7 +180,7 @@ struct ErrorMissingClosingBrace {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR invalid format string: unmatched `}`
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorMissingOpeningBrace {
     #[suggestion(typeck::suggestion, code = "name}")]
     suggestion: (Span, Applicability),
@@ -196,14 +189,14 @@ struct ErrorMissingOpeningBrace {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelOnSpan {
     #[label(typeck::label)]
     sp: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelOnNonSpan {
     #[label(typeck::label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -211,7 +204,7 @@ struct LabelOnNonSpan {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct Suggest {
     #[suggestion(typeck::suggestion, code = "This is the suggested code")]
     #[suggestion_short(typeck::suggestion, code = "This is the suggested code")]
@@ -221,14 +214,14 @@ struct Suggest {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithoutCode {
     #[suggestion(typeck::suggestion)]
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
     //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
@@ -236,7 +229,7 @@ struct SuggestWithBadKey {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
     //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
@@ -244,21 +237,21 @@ struct SuggestWithShorthandMsg {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithoutMsg {
     #[suggestion(code = "bar")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithTypesSwapped {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Span),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithWrongTypeApplicabilityOnly {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR wrong field type for suggestion
@@ -266,14 +259,14 @@ struct SuggestWithWrongTypeApplicabilityOnly {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithSpanOnly {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     suggestion: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithDuplicateSpanAndApplicability {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
@@ -281,7 +274,7 @@ struct SuggestWithDuplicateSpanAndApplicability {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithDuplicateApplicabilityAndSpan {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
@@ -289,7 +282,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct WrongKindOfAnnotation {
     #[label = "bar"]
     //~^ ERROR `#[label = ...]` is not a valid attribute
@@ -297,7 +290,7 @@ struct WrongKindOfAnnotation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct OptionsInErrors {
     #[label(typeck::label)]
     label: Option<Span>,
@@ -306,7 +299,7 @@ struct OptionsInErrors {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
 struct MoveOutOfBorrowError<'tcx> {
     name: Ident,
     ty: Ty<'tcx>,
@@ -320,7 +313,7 @@ struct MoveOutOfBorrowError<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithLifetime<'a> {
     #[label(typeck::label)]
     span: Span,
@@ -328,7 +321,7 @@ struct ErrorWithLifetime<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithDefaultLabelAttr<'a> {
     #[label]
     span: Span,
@@ -337,7 +330,7 @@ struct ErrorWithDefaultLabelAttr<'a> {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ArgFieldWithoutSkip {
     #[primary_span]
     span: Span,
@@ -345,7 +338,7 @@ struct ArgFieldWithoutSkip {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ArgFieldWithSkip {
     #[primary_span]
     span: Span,
@@ -356,56 +349,56 @@ struct ArgFieldWithSkip {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedNote {
     #[note]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedNoteCustom {
     #[note(typeck::note)]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[note]
 struct ErrorWithNote {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[note(typeck::note)]
 struct ErrorWithNoteCustom {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedHelp {
     #[help]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedHelpCustom {
     #[help(typeck::help)]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[help]
 struct ErrorWithHelp {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[help(typeck::help)]
 struct ErrorWithHelpCustom {
     val: String,
@@ -413,34 +406,34 @@ struct ErrorWithHelpCustom {
 
 #[derive(SessionDiagnostic)]
 #[help]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithHelpWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[help(typeck::help)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithHelpCustomWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[note]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNoteWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[note(typeck::note)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNoteCustomWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ApplicabilityInBoth {
     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
     //~^ ERROR applicability cannot be set in both the field and attribute
@@ -448,7 +441,7 @@ struct ApplicabilityInBoth {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct InvalidApplicability {
     #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
     //~^ ERROR invalid applicability
@@ -456,14 +449,14 @@ struct InvalidApplicability {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ValidApplicability {
     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
     suggestion: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct NoApplicability {
     #[suggestion(typeck::suggestion, code = "...")]
     suggestion: Span,
@@ -474,14 +467,14 @@ struct NoApplicability {
 struct Note;
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound)]
+#[diag(typeck::ambiguous_lifetime_bound)]
 struct Subdiagnostic {
     #[subdiagnostic]
     note: Note,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct VecField {
     #[primary_span]
     #[label]
@@ -489,7 +482,7 @@ struct VecField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct UnitField {
     #[primary_span]
     spans: Span,
@@ -500,7 +493,7 @@ struct UnitField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct OptUnitField {
     #[primary_span]
     spans: Span,
@@ -511,7 +504,7 @@ struct OptUnitField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelWithTrailingPath {
     #[label(typeck::label, foo)]
     //~^ ERROR `#[label(...)]` is not a valid attribute
@@ -519,7 +512,7 @@ struct LabelWithTrailingPath {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelWithTrailingNameValue {
     #[label(typeck::label, foo = "...")]
     //~^ ERROR `#[label(...)]` is not a valid attribute
@@ -527,32 +520,20 @@ struct LabelWithTrailingNameValue {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelWithTrailingList {
     #[label(typeck::label, foo("..."))]
     //~^ ERROR `#[label(...)]` is not a valid attribute
     span: Span,
 }
 
-#[derive(SessionDiagnostic)]
-#[lint(typeck::ambiguous_lifetime_bound)]
-//~^ ERROR only `#[error(..)]` and `#[warning(..)]` are supported
-struct LintsBad {
-}
-
 #[derive(LintDiagnostic)]
-#[lint(typeck::ambiguous_lifetime_bound)]
+#[diag(typeck::ambiguous_lifetime_bound)]
 struct LintsGood {
 }
 
 #[derive(LintDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound)]
-//~^ ERROR only `#[lint(..)]` is supported
-struct ErrorsBad {
-}
-
-#[derive(LintDiagnostic)]
-#[lint(typeck::ambiguous_lifetime_bound)]
+#[diag(typeck::ambiguous_lifetime_bound)]
 struct PrimarySpanOnLint {
     #[primary_span]
     //~^ ERROR `#[primary_span]` is not a valid attribute
@@ -560,15 +541,43 @@ struct PrimarySpanOnLint {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithMultiSpan {
     #[primary_span]
     span: MultiSpan,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[warn_]
 struct ErrorWithWarn {
     val: String,
 }
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[error(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `error` in this scope
+struct ErrorAttribute {}
+
+#[derive(SessionDiagnostic)]
+#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[warning(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `warning` in this scope
+struct WarningAttribute {}
+
+#[derive(SessionDiagnostic)]
+#[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[lint(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `lint` in this scope
+struct LintAttributeOnSessionDiag {}
+
+#[derive(LintDiagnostic)]
+#[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[lint(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `lint` in this scope
+struct LintAttributeOnLintDiag {}
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 081139c7a70..866b1a1de99 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,7 +1,7 @@
 error: `#[derive(SessionDiagnostic)]` can only be used on structs
   --> $DIR/diagnostic-derive.rs:39:1
    |
-LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | / #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
 LL | | enum SessionDiagnosticOnEnum {
 LL | |     Foo,
@@ -9,11 +9,11 @@ LL | |     Bar,
 LL | | }
    | |_^
 
-error: `#[error = ...]` is not a valid attribute
+error: `#[diag = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:48:1
    |
-LL | #[error = "E0123"]
-   | ^^^^^^^^^^^^^^^^^^
+LL | #[diag = "E0123"]
+   | ^^^^^^^^^^^^^^^^^
 
 error: `#[nonsense(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:53:1
@@ -35,18 +35,18 @@ LL | | struct InvalidStructAttr {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error("...")]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:60:9
+error: `#[diag("...")]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:60:8
    |
-LL | #[error("E0123")]
-   |         ^^^^^^^
+LL | #[diag("E0123")]
+   |        ^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:60:1
    |
-LL | / #[error("E0123")]
+LL | / #[diag("E0123")]
 LL | |
 LL | |
 LL | | struct InvalidLitNestedAttr {}
@@ -54,18 +54,18 @@ LL | | struct InvalidLitNestedAttr {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(nonsense(...))]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:71:9
+error: `#[diag(nonsense(...))]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:71:8
    |
-LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")]
-   |         ^^^^^^^^^^^^^^^
+LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+   |        ^^^^^^^^^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:71:1
    |
-LL | / #[error(nonsense("foo"), code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr1 {}
@@ -73,18 +73,18 @@ LL | | struct InvalidNestedStructAttr1 {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:77:9
+error: `#[diag(nonsense = ...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:77:8
    |
-LL | #[error(nonsense = "...", code = "E0123", slug = "foo")]
-   |         ^^^^^^^^^^^^^^^^
+LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
+   |        ^^^^^^^^^^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:77:1
    |
-LL | / #[error(nonsense = "...", code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr2 {}
@@ -92,18 +92,18 @@ LL | | struct InvalidNestedStructAttr2 {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:83:9
+error: `#[diag(nonsense = ...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:83:8
    |
-LL | #[error(nonsense = 4, code = "E0123", slug = "foo")]
-   |         ^^^^^^^^^^^^
+LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
+   |        ^^^^^^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:83:1
    |
-LL | / #[error(nonsense = 4, code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr3 {}
@@ -111,11 +111,11 @@ LL | | struct InvalidNestedStructAttr3 {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:89:59
+error: `#[diag(slug = ...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:89:58
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
-   |                                                           ^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+   |                                                          ^^^^^^^^^^^^
    |
    = help: only `code` is a valid nested attributes following the slug
 
@@ -128,71 +128,47 @@ LL |     #[suggestion = "bar"]
 error: specified multiple times
   --> $DIR/diagnostic-derive.rs:103:1
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
   --> $DIR/diagnostic-derive.rs:102:1
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:103:50
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
-   |                                                  ^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:102:50
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   |                                                  ^^^^^^^
-
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:110:1
-   |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:109:1
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:110:52
+  --> $DIR/diagnostic-derive.rs:103:49
    |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   |                                                    ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
+   |                                                 ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:109:50
+  --> $DIR/diagnostic-derive.rs:102:49
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   |                                                  ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |                                                 ^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:116:66
+  --> $DIR/diagnostic-derive.rs:109:65
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
-   |                                                                  ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                                 ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:116:50
+  --> $DIR/diagnostic-derive.rs:109:49
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
-   |                                                  ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                 ^^^^^^^
 
-error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:121:43
+error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:114:42
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:126:1
+  --> $DIR/diagnostic-derive.rs:119:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -200,9 +176,9 @@ LL | struct KindNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:129:1
+  --> $DIR/diagnostic-derive.rs:122:1
    |
-LL | / #[error(code = "E0456")]
+LL | / #[diag(code = "E0456")]
 LL | |
 LL | | struct SlugNotProvided {}
    | |_________________________^
@@ -210,13 +186,13 @@ LL | | struct SlugNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:140:5
+  --> $DIR/diagnostic-derive.rs:133:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:148:5
+  --> $DIR/diagnostic-derive.rs:141:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
@@ -224,19 +200,19 @@ LL |     #[nonsense]
    = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:165:5
+  --> $DIR/diagnostic-derive.rs:158:5
    |
 LL |     #[label(typeck::label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:173:45
+  --> $DIR/diagnostic-derive.rs:166:45
    |
 LL |     #[suggestion(typeck::suggestion, code = "{name}")]
    |                                             ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:178:16
+  --> $DIR/diagnostic-derive.rs:171:16
    |
 LL | #[derive(SessionDiagnostic)]
    |           -    ^ expected `'}'` in format string
@@ -247,7 +223,7 @@ LL | #[derive(SessionDiagnostic)]
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:188:15
+  --> $DIR/diagnostic-derive.rs:181:15
    |
 LL | #[derive(SessionDiagnostic)]
    |               ^ unmatched `}` in format string
@@ -256,13 +232,13 @@ LL | #[derive(SessionDiagnostic)]
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:208:5
+  --> $DIR/diagnostic-derive.rs:201:5
    |
 LL |     #[label(typeck::label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:233:18
+  --> $DIR/diagnostic-derive.rs:226:18
    |
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^^^^^^^^^
@@ -270,7 +246,7 @@ LL |     #[suggestion(nonsense = "bar")]
    = help: only `message`, `code` and `applicability` are valid field attributes
 
 error: `#[suggestion(msg = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:241:18
+  --> $DIR/diagnostic-derive.rs:234:18
    |
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^^^^^^^^^
@@ -278,7 +254,7 @@ LL |     #[suggestion(msg = "bar")]
    = help: only `message`, `code` and `applicability` are valid field attributes
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:263:5
+  --> $DIR/diagnostic-derive.rs:256:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -288,7 +264,7 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
-  --> $DIR/diagnostic-derive.rs:278:5
+  --> $DIR/diagnostic-derive.rs:271:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -296,7 +272,7 @@ LL | |     suggestion: (Span, Span, Applicability),
    | |___________________________________________^
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
-  --> $DIR/diagnostic-derive.rs:286:5
+  --> $DIR/diagnostic-derive.rs:279:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -304,64 +280,128 @@ LL | |     suggestion: (Applicability, Applicability, Span),
    | |____________________________________________________^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:294:5
+  --> $DIR/diagnostic-derive.rs:287:5
    |
 LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: applicability cannot be set in both the field and attribute
-  --> $DIR/diagnostic-derive.rs:445:52
+  --> $DIR/diagnostic-derive.rs:438:52
    |
 LL |     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:453:52
+  --> $DIR/diagnostic-derive.rs:446:52
    |
 LL |     #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:516:5
+  --> $DIR/diagnostic-derive.rs:509:5
    |
 LL |     #[label(typeck::label, foo)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:524:5
+  --> $DIR/diagnostic-derive.rs:517:5
    |
 LL |     #[label(typeck::label, foo = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:532:5
+  --> $DIR/diagnostic-derive.rs:525:5
    |
 LL |     #[label(typeck::label, foo("..."))]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: only `#[error(..)]` and `#[warning(..)]` are supported
-  --> $DIR/diagnostic-derive.rs:538:1
+error: `#[primary_span]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:538:5
    |
-LL | #[lint(typeck::ambiguous_lifetime_bound)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[primary_span]
+   |     ^^^^^^^^^^^^^^^
    |
-   = help: use the `#[error(...)]` attribute to create a error
+   = help: the `primary_span` field attribute is not valid for lint diagnostics
 
-error: only `#[lint(..)]` is supported
-  --> $DIR/diagnostic-derive.rs:549:1
+error: `#[error(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:558:1
    |
-LL | #[error(typeck::ambiguous_lifetime_bound)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use the `#[lint(...)]` attribute to create a lint
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
 
-error: `#[primary_span]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:557:5
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:558:1
    |
-LL |     #[primary_span]
-   |     ^^^^^^^^^^^^^^^
+LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | |
+LL | |
+LL | | struct ErrorAttribute {}
+   | |________________________^
    |
-   = help: the `primary_span` field attribute is not valid for lint diagnostics
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+
+error: `#[warning(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:565:1
+   |
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:565:1
+   |
+LL | / #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | |
+LL | |
+LL | | struct WarningAttribute {}
+   | |__________________________^
+   |
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+
+error: `#[lint(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:572:1
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:572:1
+   |
+LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | |
+LL | |
+LL | | struct LintAttributeOnSessionDiag {}
+   | |____________________________________^
+   |
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+
+error: `#[lint(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:579:1
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:579:1
+   |
+LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | |
+LL | |
+LL | | struct LintAttributeOnLintDiag {}
+   | |_________________________________^
+   |
+   = help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]`
 
 error: cannot find attribute `nonsense` in this scope
   --> $DIR/diagnostic-derive.rs:53:3
@@ -370,19 +410,43 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:148:7
+  --> $DIR/diagnostic-derive.rs:141:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
+error: cannot find attribute `error` in this scope
+  --> $DIR/diagnostic-derive.rs:558:3
+   |
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^^
+
+error: cannot find attribute `warning` in this scope
+  --> $DIR/diagnostic-derive.rs:565:3
+   |
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^^^^
+
+error: cannot find attribute `lint` in this scope
+  --> $DIR/diagnostic-derive.rs:572:3
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^ help: a built-in attribute with a similar name exists: `link`
+
+error: cannot find attribute `lint` in this scope
+  --> $DIR/diagnostic-derive.rs:579:3
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^ help: a built-in attribute with a similar name exists: `link`
+
 error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
-  --> $DIR/diagnostic-derive.rs:66:9
+  --> $DIR/diagnostic-derive.rs:66:8
    |
-LL | #[error(nonsense, code = "E0123")]
-   |         ^^^^^^^^ not found in `rustc_errors::fluent`
+LL | #[diag(nonsense, code = "E0123")]
+   |        ^^^^^^^^ not found in `rustc_errors::fluent`
 
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:338:10
+  --> $DIR/diagnostic-derive.rs:331:10
    |
 LL | #[derive(SessionDiagnostic)]
    |          ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
@@ -395,7 +459,7 @@ LL |         arg: impl IntoDiagnosticArg,
    |                   ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 47 previous errors
+error: aborting due to 55 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.