about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-21 10:04:42 +0000
committerbors <bors@rust-lang.org>2022-08-21 10:04:42 +0000
commit4b695f7c4e1a02d160fe7e159abd0f87027c0fcf (patch)
tree2c7322f5189d638990acf9ad89b5cec9e3aeb6c0 /src
parent39a9b88f4e50d4c0204bb12c0821b49a302ab3c5 (diff)
parent7f3a6fd7f6c04635f3d541201199f127f2a2e65e (diff)
Auto merge of #100765 - Xiretza:session-diagnostic-unification, r=compiler-errors
Kind-less SessionDiagnostic derive

From https://github.com/rust-lang/rust/pull/100730#discussion_r949712629:

> Hm, maybe we should expose some `sess.struct_$SOMETHING` (like `struct_diagnostic`?) that is generic over `EmissionGuarantee`, then make the `SessionDiagnostic` derive generic, i.e.
>
> ```rust
> impl<'tcx> SessionDiagnostic for UnusedGenericParams {
>   fn into_diagnostic<T: EmissionGuarantee>( .. ) -> DiagnosticBuilder<'tcx, T> {
>     let mut diag = sess.struct_diagnostic(rustc_errors:..);
>     ..
>   }
> }
> ```

Discussed [on Zulip](https://rust-lang.zulipchat.com/#narrow/stream/147480-t-compiler.2Fwg-diagnostics/topic/.23100717.20translation.20-.20kind-less.20derive).
Diffstat (limited to 'src')
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.rs2
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs211
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr338
3 files changed, 304 insertions, 247 deletions
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 0a210cbdc94..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,54 +44,54 @@ 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)]
 #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
 //~^ ERROR `#[nonsense(...)]` is not a valid attribute
-//~^^ ERROR diagnostic kind not specified
+//~^^ ERROR diagnostic slug not specified
 //~^^^ ERROR cannot find attribute `nonsense` in this scope
 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,45 +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
-//~^^^ 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
-//~^^^ 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 kind not specified
+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`
@@ -145,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
@@ -154,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)]
@@ -162,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`
@@ -170,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
@@ -179,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),
@@ -189,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),
@@ -198,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`
@@ -213,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")]
@@ -223,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
@@ -238,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
@@ -246,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
@@ -268,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`
@@ -283,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
@@ -291,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
@@ -299,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>,
@@ -308,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>,
@@ -322,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,
@@ -330,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,
@@ -339,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,
@@ -347,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,
@@ -358,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,
@@ -415,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
@@ -450,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
@@ -458,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,
@@ -476,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]
@@ -491,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,
@@ -502,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,
@@ -513,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
@@ -521,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
@@ -529,40 +520,64 @@ 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 {
+#[diag(typeck::ambiguous_lifetime_bound)]
+struct PrimarySpanOnLint {
+    #[primary_span]
+    //~^ ERROR `#[primary_span]` is not a valid attribute
+    span: Span,
 }
 
 #[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 c1080aa2452..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
@@ -21,9 +21,9 @@ error: `#[nonsense(...)]` is not a valid attribute
 LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: only `error`, `warning`, `help`, `note` and `warn_` are valid attributes
+   = help: only `diag`, `help`, `note` and `warn_` are valid attributes
 
-error: diagnostic kind not specified
+error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:53:1
    |
 LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
@@ -33,89 +33,89 @@ LL | |
 LL | | struct InvalidStructAttr {}
    | |___________________________^
    |
-   = help: use the `#[error(...)]` attribute to create an error
+   = 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 {}
    | |______________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = 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 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = 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 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = 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 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = 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,119 +128,71 @@ 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")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:103:1
+  --> $DIR/diagnostic-derive.rs:103:49
    |
-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
+  --> $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:103:50
+  --> $DIR/diagnostic-derive.rs:109:65
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
-   |                                                  ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                                 ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:102:50
+  --> $DIR/diagnostic-derive.rs:109:49
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   |                                                  ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                 ^^^^^^^
 
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:111:1
+error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:114:42
    |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:110:1
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:111:1
-   |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:110:1
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:111:52
-   |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   |                                                    ^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:110:50
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   |                                                  ^^^^^^^
-
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:118:66
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
-   |                                                                  ^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:118:50
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
-   |                                                  ^^^^^^^
-
-error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:123:43
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: diagnostic kind not specified
-  --> $DIR/diagnostic-derive.rs:128:1
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:119:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use the `#[error(...)]` attribute to create an error
+   = 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:131:1
+  --> $DIR/diagnostic-derive.rs:122:1
    |
-LL | / #[error(code = "E0456")]
+LL | / #[diag(code = "E0456")]
 LL | |
 LL | | struct SlugNotProvided {}
    | |_________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = 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:142:5
+  --> $DIR/diagnostic-derive.rs:133:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:150:5
+  --> $DIR/diagnostic-derive.rs:141:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
@@ -248,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:167: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:175: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:180:16
+  --> $DIR/diagnostic-derive.rs:171:16
    |
 LL | #[derive(SessionDiagnostic)]
    |           -    ^ expected `'}'` in format string
@@ -271,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:190:15
+  --> $DIR/diagnostic-derive.rs:181:15
    |
 LL | #[derive(SessionDiagnostic)]
    |               ^ unmatched `}` in format string
@@ -280,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:210:5
+  --> $DIR/diagnostic-derive.rs:201:5
    |
 LL |     #[label(typeck::label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:235:18
+  --> $DIR/diagnostic-derive.rs:226:18
    |
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^^^^^^^^^
@@ -294,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:243:18
+  --> $DIR/diagnostic-derive.rs:234:18
    |
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^^^^^^^^^
@@ -302,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:265:5
+  --> $DIR/diagnostic-derive.rs:256:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -312,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:280:5
+  --> $DIR/diagnostic-derive.rs:271:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -320,7 +272,7 @@ LL | |     suggestion: (Span, Span, Applicability),
    | |___________________________________________^
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
-  --> $DIR/diagnostic-derive.rs:288:5
+  --> $DIR/diagnostic-derive.rs:279:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -328,62 +280,128 @@ LL | |     suggestion: (Applicability, Applicability, Span),
    | |____________________________________________________^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:296: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:447:52
+  --> $DIR/diagnostic-derive.rs:438:52
    |
 LL |     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:455: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:518:5
+  --> $DIR/diagnostic-derive.rs:509:5
    |
 LL |     #[label(typeck::label, foo)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:526:5
+  --> $DIR/diagnostic-derive.rs:517:5
    |
 LL |     #[label(typeck::label, foo = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:534:5
+  --> $DIR/diagnostic-derive.rs:525:5
    |
 LL |     #[label(typeck::label, foo("..."))]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: only `#[error(..)]` and `#[warning(..)]` are supported
-  --> $DIR/diagnostic-derive.rs:540: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: the `primary_span` field attribute is not valid for lint diagnostics
+
+error: `#[error(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:558:1
+   |
+LL | #[error(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:558:1
+   |
+LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
-LL | | struct LintsBad {
-LL | | }
-   | |_^
+LL | |
+LL | |
+LL | | struct ErrorAttribute {}
+   | |________________________^
+   |
+   = 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
    |
-   = help: use the `#[error(...)]` attribute to create a error
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
 
-error: only `#[lint(..)]` is supported
-  --> $DIR/diagnostic-derive.rs:551:1
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:565:1
    |
-LL | / #[error(typeck::ambiguous_lifetime_bound)]
+LL | / #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
-LL | | struct ErrorsBad {
-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: use the `#[lint(...)]` attribute to create a lint
+   = 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
@@ -392,32 +410,56 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:150: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:340:10
+  --> $DIR/diagnostic-derive.rs:331:10
    |
 LL | #[derive(SessionDiagnostic)]
    |          ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
    |
    = help: normalized in stderr
 note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
-  --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:539:19
+  --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:569:19
    |
 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 48 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`.