summaryrefslogtreecommitdiffstats
path: root/src/test/ui-fulldeps/session-diagnostic
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui-fulldeps/session-diagnostic
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui-fulldeps/session-diagnostic')
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs568
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr423
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs522
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr400
4 files changed, 1913 insertions, 0 deletions
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
new file mode 100644
index 000000000..0a210cbdc
--- /dev/null
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -0,0 +1,568 @@
+// check-fail
+// Tests error conditions for specifying diagnostics using #[derive(SessionDiagnostic)]
+
+// normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
+
+// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
+// changing the output of this test. Since SessionDiagnostic is strictly internal to the compiler
+// the test is just ignored on stable and beta:
+// ignore-beta
+// ignore-stable
+
+#![feature(rustc_private)]
+#![crate_type = "lib"]
+
+extern crate rustc_span;
+use rustc_span::symbol::Ident;
+use rustc_span::Span;
+
+extern crate rustc_macros;
+use rustc_macros::{SessionDiagnostic, LintDiagnostic, SessionSubdiagnostic};
+
+extern crate rustc_middle;
+use rustc_middle::ty::Ty;
+
+extern crate rustc_errors;
+use rustc_errors::{Applicability, MultiSpan};
+
+extern crate rustc_session;
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct Hello {}
+
+#[derive(SessionDiagnostic)]
+#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct HelloWarn {}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs
+enum SessionDiagnosticOnEnum {
+ Foo,
+ Bar,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[error = "E0123"]
+//~^ ERROR `#[error = ...]` 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 cannot find attribute `nonsense` in this scope
+struct InvalidStructAttr {}
+
+#[derive(SessionDiagnostic)]
+#[error("E0123")]
+//~^ ERROR `#[error("...")]` is not a valid attribute
+//~^^ ERROR diagnostic slug not specified
+struct InvalidLitNestedAttr {}
+
+#[derive(SessionDiagnostic)]
+#[error(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
+//~^^ ERROR diagnostic slug not specified
+struct InvalidNestedStructAttr1 {}
+
+#[derive(SessionDiagnostic)]
+#[error(nonsense = "...", code = "E0123", slug = "foo")]
+//~^ ERROR `#[error(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
+//~^^ 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
+struct InvalidNestedStructAttr4 {}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct WrongPlaceField {
+ #[suggestion = "bar"]
+ //~^ ERROR `#[suggestion = ...]` is not a valid attribute
+ sp: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+//~^ ERROR specified multiple times
+//~^^ ERROR specified multiple times
+//~^^^ ERROR specified multiple times
+struct ErrorSpecifiedTwice {}
+
+#[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")]
+//~^ 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
+struct SlugSpecifiedTwice {}
+
+#[derive(SessionDiagnostic)]
+struct KindNotProvided {} //~ ERROR diagnostic kind not specified
+
+#[derive(SessionDiagnostic)]
+#[error(code = "E0456")]
+//~^ ERROR diagnostic slug not specified
+struct SlugNotProvided {}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound)]
+struct CodeNotProvided {}
+
+#[derive(SessionDiagnostic)]
+#[error(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`
+ foo: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct InvalidPathFieldAttr {
+ #[nonsense]
+ //~^ ERROR `#[nonsense]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `nonsense` in this scope
+ foo: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithField {
+ name: String,
+ #[label(typeck::label)]
+ span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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`
+ name: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithNonexistentField {
+ #[suggestion(typeck::suggestion, code = "{name}")]
+ //~^ ERROR `name` doesn't refer to a field on this type
+ suggestion: (Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+//~^ ERROR invalid format string: expected `'}'`
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorMissingClosingBrace {
+ #[suggestion(typeck::suggestion, code = "{name")]
+ suggestion: (Span, Applicability),
+ name: String,
+ val: usize,
+}
+
+#[derive(SessionDiagnostic)]
+//~^ ERROR invalid format string: unmatched `}`
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorMissingOpeningBrace {
+ #[suggestion(typeck::suggestion, code = "name}")]
+ suggestion: (Span, Applicability),
+ name: String,
+ val: usize,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct LabelOnSpan {
+ #[label(typeck::label)]
+ sp: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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`
+ id: u32,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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")]
+ #[suggestion_hidden(typeck::suggestion, code = "This is the suggested code")]
+ #[suggestion_verbose(typeck::suggestion, code = "This is the suggested code")]
+ suggestion: (Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct SuggestWithoutCode {
+ #[suggestion(typeck::suggestion)]
+ suggestion: (Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct SuggestWithBadKey {
+ #[suggestion(nonsense = "bar")]
+ //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
+ suggestion: (Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct SuggestWithShorthandMsg {
+ #[suggestion(msg = "bar")]
+ //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
+ suggestion: (Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct SuggestWithoutMsg {
+ #[suggestion(code = "bar")]
+ suggestion: (Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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")]
+struct SuggestWithWrongTypeApplicabilityOnly {
+ #[suggestion(typeck::suggestion, code = "This is suggested code")]
+ //~^ ERROR wrong field type for suggestion
+ suggestion: Applicability,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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")]
+struct SuggestWithDuplicateSpanAndApplicability {
+ #[suggestion(typeck::suggestion, code = "This is suggested code")]
+ //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
+ suggestion: (Span, Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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
+ suggestion: (Applicability, Applicability, Span),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct WrongKindOfAnnotation {
+ #[label = "bar"]
+ //~^ ERROR `#[label = ...]` is not a valid attribute
+ z: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct OptionsInErrors {
+ #[label(typeck::label)]
+ label: Option<Span>,
+ #[suggestion(typeck::suggestion)]
+ opt_sugg: Option<(Span, Applicability)>,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+struct MoveOutOfBorrowError<'tcx> {
+ name: Ident,
+ ty: Ty<'tcx>,
+ #[primary_span]
+ #[label(typeck::label)]
+ span: Span,
+ #[label(typeck::label)]
+ other_span: Span,
+ #[suggestion(typeck::suggestion, code = "{name}.clone()")]
+ opt_sugg: Option<(Span, Applicability)>,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithLifetime<'a> {
+ #[label(typeck::label)]
+ span: Span,
+ name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithDefaultLabelAttr<'a> {
+ #[label]
+ span: Span,
+ name: &'a str,
+}
+
+#[derive(SessionDiagnostic)]
+//~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ArgFieldWithoutSkip {
+ #[primary_span]
+ span: Span,
+ other: Hello,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ArgFieldWithSkip {
+ #[primary_span]
+ span: Span,
+ // `Hello` does not implement `IntoDiagnosticArg` so this would result in an error if
+ // not for `#[skip_arg]`.
+ #[skip_arg]
+ other: Hello,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithSpannedNote {
+ #[note]
+ span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithSpannedNoteCustom {
+ #[note(typeck::note)]
+ span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[note]
+struct ErrorWithNote {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[note(typeck::note)]
+struct ErrorWithNoteCustom {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithSpannedHelp {
+ #[help]
+ span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithSpannedHelpCustom {
+ #[help(typeck::help)]
+ span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[help]
+struct ErrorWithHelp {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[help(typeck::help)]
+struct ErrorWithHelpCustom {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[help]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithHelpWrongOrder {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[help(typeck::help)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithHelpCustomWrongOrder {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[note]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithNoteWrongOrder {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[note(typeck::note)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithNoteCustomWrongOrder {
+ val: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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
+ suggestion: (Span, Applicability),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct InvalidApplicability {
+ #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
+ //~^ ERROR invalid applicability
+ suggestion: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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")]
+struct NoApplicability {
+ #[suggestion(typeck::suggestion, code = "...")]
+ suggestion: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[note(parser::add_paren)]
+struct Note;
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound)]
+struct Subdiagnostic {
+ #[subdiagnostic]
+ note: Note,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct VecField {
+ #[primary_span]
+ #[label]
+ spans: Vec<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct UnitField {
+ #[primary_span]
+ spans: Span,
+ #[help]
+ foo: (),
+ #[help(typeck::help)]
+ bar: (),
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct OptUnitField {
+ #[primary_span]
+ spans: Span,
+ #[help]
+ foo: Option<()>,
+ #[help(typeck::help)]
+ bar: Option<()>,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct LabelWithTrailingPath {
+ #[label(typeck::label, foo)]
+ //~^ ERROR `#[label(...)]` is not a valid attribute
+ span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct LabelWithTrailingNameValue {
+ #[label(typeck::label, foo = "...")]
+ //~^ ERROR `#[label(...)]` is not a valid attribute
+ span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(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)]
+struct LintsGood {
+}
+
+#[derive(LintDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound)]
+//~^ ERROR only `#[lint(..)]` is supported
+struct ErrorsBad {
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+struct ErrorWithMultiSpan {
+ #[primary_span]
+ span: MultiSpan,
+}
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[warn_]
+struct ErrorWithWarn {
+ val: String,
+}
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
new file mode 100644
index 000000000..c1080aa24
--- /dev/null
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -0,0 +1,423 @@
+error: `#[derive(SessionDiagnostic)]` can only be used on structs
+ --> $DIR/diagnostic-derive.rs:39:1
+ |
+LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | | enum SessionDiagnosticOnEnum {
+LL | | Foo,
+LL | | Bar,
+LL | | }
+ | |_^
+
+error: `#[error = ...]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:48:1
+ |
+LL | #[error = "E0123"]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: `#[nonsense(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:53:1
+ |
+LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: only `error`, `warning`, `help`, `note` and `warn_` are valid attributes
+
+error: diagnostic kind not specified
+ --> $DIR/diagnostic-derive.rs:53:1
+ |
+LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | |
+LL | |
+LL | | struct InvalidStructAttr {}
+ | |___________________________^
+ |
+ = help: use the `#[error(...)]` attribute to create an error
+
+error: `#[error("...")]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:60:9
+ |
+LL | #[error("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 | |
+LL | |
+LL | | struct InvalidLitNestedAttr {}
+ | |______________________________^
+ |
+ = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+
+error: `#[error(nonsense(...))]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:71:9
+ |
+LL | #[error(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 | |
+LL | |
+LL | | struct InvalidNestedStructAttr1 {}
+ | |__________________________________^
+ |
+ = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+
+error: `#[error(nonsense = ...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:77:9
+ |
+LL | #[error(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 | |
+LL | |
+LL | | struct InvalidNestedStructAttr2 {}
+ | |__________________________________^
+ |
+ = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+
+error: `#[error(nonsense = ...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:83:9
+ |
+LL | #[error(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 | |
+LL | |
+LL | | struct InvalidNestedStructAttr3 {}
+ | |__________________________________^
+ |
+ = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+
+error: `#[error(slug = ...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:89:59
+ |
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+ | ^^^^^^^^^^^^
+ |
+ = help: only `code` is a valid nested attributes following the slug
+
+error: `#[suggestion = ...]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:96:5
+ |
+LL | #[suggestion = "bar"]
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: specified multiple times
+ --> $DIR/diagnostic-derive.rs:103:1
+ |
+LL | #[error(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:1
+ |
+LL | #[error(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: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: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
+ |
+LL | struct KindNotProvided {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use the `#[error(...)]` attribute to create an error
+
+error: diagnostic slug not specified
+ --> $DIR/diagnostic-derive.rs:131:1
+ |
+LL | / #[error(code = "E0456")]
+LL | |
+LL | | struct SlugNotProvided {}
+ | |_________________________^
+ |
+ = help: specify the slug as the first argument to the attribute, such as `#[error(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
+ |
+LL | #[primary_span]
+ | ^^^^^^^^^^^^^^^
+
+error: `#[nonsense]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:150:5
+ |
+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
+ |
+LL | #[label(typeck::label)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `name` doesn't refer to a field on this type
+ --> $DIR/diagnostic-derive.rs:175:45
+ |
+LL | #[suggestion(typeck::suggestion, code = "{name}")]
+ | ^^^^^^^^
+
+error: invalid format string: expected `'}'` but string was terminated
+ --> $DIR/diagnostic-derive.rs:180:16
+ |
+LL | #[derive(SessionDiagnostic)]
+ | - ^ expected `'}'` in format string
+ | |
+ | because of this opening brace
+ |
+ = note: if you intended to print `{`, you can escape it using `{{`
+ = 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
+ |
+LL | #[derive(SessionDiagnostic)]
+ | ^ unmatched `}` in format string
+ |
+ = note: if you intended to print `}`, you can escape it using `}}`
+ = 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
+ |
+LL | #[label(typeck::label)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[suggestion(nonsense = ...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:235:18
+ |
+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
+ |
+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
+ |
+LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
+LL | |
+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
+ |
+LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
+LL | |
+LL | | suggestion: (Span, Span, Applicability),
+ | |___________________________________________^
+
+error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
+ --> $DIR/diagnostic-derive.rs:288:5
+ |
+LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
+LL | |
+LL | | suggestion: (Applicability, Applicability, Span),
+ | |____________________________________________________^
+
+error: `#[label = ...]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:296:5
+ |
+LL | #[label = "bar"]
+ | ^^^^^^^^^^^^^^^^
+
+error: applicability cannot be set in both the field and attribute
+ --> $DIR/diagnostic-derive.rs:447:52
+ |
+LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: invalid applicability
+ --> $DIR/diagnostic-derive.rs:455:52
+ |
+LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[label(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:518:5
+ |
+LL | #[label(typeck::label, foo)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[label(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:526:5
+ |
+LL | #[label(typeck::label, foo = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[label(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:534:5
+ |
+LL | #[label(typeck::label, foo("..."))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: only `#[error(..)]` and `#[warning(..)]` are supported
+ --> $DIR/diagnostic-derive.rs:540:1
+ |
+LL | / #[lint(typeck::ambiguous_lifetime_bound)]
+LL | |
+LL | | struct LintsBad {
+LL | | }
+ | |_^
+ |
+ = help: use the `#[error(...)]` attribute to create a error
+
+error: only `#[lint(..)]` is supported
+ --> $DIR/diagnostic-derive.rs:551:1
+ |
+LL | / #[error(typeck::ambiguous_lifetime_bound)]
+LL | |
+LL | | struct ErrorsBad {
+LL | | }
+ | |_^
+ |
+ = help: use the `#[lint(...)]` attribute to create a lint
+
+error: cannot find attribute `nonsense` in this scope
+ --> $DIR/diagnostic-derive.rs:53:3
+ |
+LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
+ | ^^^^^^^^
+
+error: cannot find attribute `nonsense` in this scope
+ --> $DIR/diagnostic-derive.rs:150:7
+ |
+LL | #[nonsense]
+ | ^^^^^^^^
+
+error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
+ --> $DIR/diagnostic-derive.rs:66:9
+ |
+LL | #[error(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
+ |
+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
+ |
+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
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
new file mode 100644
index 000000000..16da25c40
--- /dev/null
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -0,0 +1,522 @@
+// check-fail
+// Tests error conditions for specifying subdiagnostics using #[derive(SessionSubdiagnostic)]
+
+// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
+// changing the output of this test. Since SessionSubdiagnostic is strictly internal to the compiler
+// the test is just ignored on stable and beta:
+// ignore-beta
+// ignore-stable
+
+#![feature(rustc_private)]
+#![crate_type = "lib"]
+
+extern crate rustc_errors;
+extern crate rustc_session;
+extern crate rustc_span;
+extern crate rustc_macros;
+
+use rustc_errors::Applicability;
+use rustc_span::Span;
+use rustc_macros::SessionSubdiagnostic;
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+struct A {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+enum B {
+ #[label(parser::add_paren)]
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ },
+ #[label(parser::add_paren)]
+ B {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+//~^ ERROR label without `#[primary_span]` field
+struct C {
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label]
+//~^ ERROR `#[label]` is not a valid attribute
+struct D {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[foo]
+//~^ ERROR `#[foo]` is not a valid attribute
+//~^^ ERROR cannot find attribute `foo` in this scope
+struct E {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label = "..."]
+//~^ ERROR `#[label = ...]` is not a valid attribute
+struct F {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(bug = "...")]
+//~^ ERROR `#[label(bug = ...)]` is not a valid attribute
+struct G {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label("...")]
+//~^ ERROR `#[label("...")]` is not a valid attribute
+struct H {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(slug = 4)]
+//~^ ERROR `#[label(slug = ...)]` is not a valid attribute
+struct J {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(slug("..."))]
+//~^ ERROR `#[label(slug(...))]` is not a valid attribute
+struct K {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(slug)]
+//~^ ERROR cannot find value `slug` in module `rustc_errors::fluent`
+//~^^ NOTE not found in `rustc_errors::fluent`
+struct L {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label()]
+//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
+struct M {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren, code = "...")]
+//~^ ERROR `code` is not a valid nested attribute of a `label` attribute
+struct N {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren, applicability = "machine-applicable")]
+//~^ ERROR `applicability` is not a valid nested attribute of a `label` attribute
+struct O {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[foo]
+//~^ ERROR cannot find attribute `foo` in this scope
+//~^^ ERROR unsupported type attribute for subdiagnostic enum
+enum P {
+ #[label(parser::add_paren)]
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+enum Q {
+ #[bar]
+//~^ ERROR `#[bar]` is not a valid attribute
+//~^^ ERROR cannot find attribute `bar` in this scope
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+enum R {
+ #[bar = "..."]
+//~^ ERROR `#[bar = ...]` is not a valid attribute
+//~^^ ERROR cannot find attribute `bar` in this scope
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+enum S {
+ #[bar = 4]
+//~^ ERROR `#[bar = ...]` is not a valid attribute
+//~^^ ERROR cannot find attribute `bar` in this scope
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+enum T {
+ #[bar("...")]
+//~^ ERROR `#[bar("...")]` is not a valid attribute
+//~^^ ERROR cannot find attribute `bar` in this scope
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+enum U {
+ #[label(code = "...")]
+//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+enum V {
+ #[label(parser::add_paren)]
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ },
+ B {
+//~^ ERROR subdiagnostic kind not specified
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+//~^ ERROR label without `#[primary_span]` field
+struct W {
+ #[primary_span]
+ //~^ ERROR the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+ span: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+struct X {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+ //~^ ERROR `#[applicability]` is only valid on suggestions
+ applicability: Applicability,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+struct Y {
+ #[primary_span]
+ span: Span,
+ #[bar]
+ //~^ ERROR `#[bar]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `bar` in this scope
+ bar: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+struct Z {
+ #[primary_span]
+ span: Span,
+ #[bar = "..."]
+ //~^ ERROR `#[bar = ...]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `bar` in this scope
+ bar: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+struct AA {
+ #[primary_span]
+ span: Span,
+ #[bar("...")]
+ //~^ ERROR `#[bar(...)]` is not a valid attribute
+ //~^^ ERROR cannot find attribute `bar` in this scope
+ bar: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+struct AB {
+ #[primary_span]
+ span: Span,
+ #[skip_arg]
+ z: Z
+}
+
+#[derive(SessionSubdiagnostic)]
+union AC {
+//~^ ERROR unexpected unsupported untagged union
+ span: u32,
+ b: u64
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+//~^ NOTE previously specified here
+//~^^ NOTE previously specified here
+#[label(parser::add_paren)]
+//~^ ERROR specified multiple times
+//~^^ ERROR specified multiple times
+struct AD {
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren, parser::add_paren)]
+//~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute
+struct AE {
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label(parser::add_paren)]
+struct AF {
+ #[primary_span]
+//~^ NOTE previously specified here
+ span_a: Span,
+ #[primary_span]
+//~^ ERROR specified multiple times
+ span_b: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+struct AG {
+//~^ ERROR subdiagnostic kind not specified
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...")]
+struct AH {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+ applicability: Applicability,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+enum AI {
+ #[suggestion(parser::add_paren, code = "...")]
+ A {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+ applicability: Applicability,
+ var: String,
+ },
+ #[suggestion(parser::add_paren, code = "...")]
+ B {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+ applicability: Applicability,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...", code = "...")]
+//~^ ERROR specified multiple times
+//~^^ NOTE previously specified here
+struct AJ {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+ applicability: Applicability,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...")]
+struct AK {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+//~^ NOTE previously specified here
+ applicability_a: Applicability,
+ #[applicability]
+//~^ ERROR specified multiple times
+ applicability_b: Applicability,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...")]
+//~^ ERROR suggestion without `applicability`
+struct AL {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+//~^ ERROR the `#[applicability]` attribute can only be applied to fields of type `Applicability`
+ applicability: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...")]
+//~^ ERROR suggestion without `applicability`
+struct AM {
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren)]
+//~^ ERROR suggestion without `code = "..."`
+struct AN {
+ #[primary_span]
+ span: Span,
+ #[applicability]
+ applicability: Applicability,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code ="...", applicability = "foo")]
+//~^ ERROR invalid applicability
+struct AO {
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[help(parser::add_paren)]
+struct AP {
+ var: String
+}
+
+#[derive(SessionSubdiagnostic)]
+#[note(parser::add_paren)]
+struct AQ;
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code = "...")]
+//~^ ERROR suggestion without `applicability`
+//~^^ ERROR suggestion without `#[primary_span]` field
+struct AR {
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code ="...", applicability = "machine-applicable")]
+struct AS {
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[label]
+//~^ ERROR unsupported type attribute for subdiagnostic enum
+enum AT {
+ #[label(parser::add_paren)]
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+struct AU {
+ #[primary_span]
+ span: Span,
+ var: String,
+}
+
+#[derive(SessionSubdiagnostic)]
+#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+//~^ ERROR `var` doesn't refer to a field on this type
+struct AV {
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(SessionSubdiagnostic)]
+enum AW {
+ #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+ A {
+ #[primary_span]
+ span: Span,
+ var: String,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+enum AX {
+ #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+//~^ ERROR `var` doesn't refer to a field on this type
+ A {
+ #[primary_span]
+ span: Span,
+ }
+}
+
+#[derive(SessionSubdiagnostic)]
+#[warn_(parser::add_paren)]
+struct AY {
+}
+
+#[derive(SessionSubdiagnostic)]
+#[warn_(parser::add_paren)]
+struct AZ {
+ #[primary_span]
+ span: Span,
+}
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
new file mode 100644
index 000000000..a289c4fff
--- /dev/null
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -0,0 +1,400 @@
+error: label without `#[primary_span]` field
+ --> $DIR/subdiagnostic-derive.rs:47:1
+ |
+LL | / #[label(parser::add_paren)]
+LL | |
+LL | | struct C {
+LL | | var: String,
+LL | | }
+ | |_^
+
+error: `#[label]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:54:1
+ |
+LL | #[label]
+ | ^^^^^^^^
+
+error: `#[foo]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:63:1
+ |
+LL | #[foo]
+ | ^^^^^^
+
+error: `#[label = ...]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:73:1
+ |
+LL | #[label = "..."]
+ | ^^^^^^^^^^^^^^^^
+
+error: `#[label(bug = ...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:82:9
+ |
+LL | #[label(bug = "...")]
+ | ^^^^^^^^^^^
+ |
+ = help: first argument of the attribute should be the diagnostic slug
+
+error: `#[label("...")]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:91:9
+ |
+LL | #[label("...")]
+ | ^^^^^
+ |
+ = help: first argument of the attribute should be the diagnostic slug
+
+error: `#[label(slug = ...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:100:9
+ |
+LL | #[label(slug = 4)]
+ | ^^^^^^^^
+ |
+ = help: first argument of the attribute should be the diagnostic slug
+
+error: `#[label(slug(...))]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:109:9
+ |
+LL | #[label(slug("..."))]
+ | ^^^^^^^^^^^
+ |
+ = help: first argument of the attribute should be the diagnostic slug
+
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+ --> $DIR/subdiagnostic-derive.rs:128:1
+ |
+LL | #[label()]
+ | ^^^^^^^^^^
+
+error: `code` is not a valid nested attribute of a `label` attribute
+ --> $DIR/subdiagnostic-derive.rs:137:1
+ |
+LL | #[label(parser::add_paren, code = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `applicability` is not a valid nested attribute of a `label` attribute
+ --> $DIR/subdiagnostic-derive.rs:146:1
+ |
+LL | #[label(parser::add_paren, applicability = "machine-applicable")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unsupported type attribute for subdiagnostic enum
+ --> $DIR/subdiagnostic-derive.rs:155:1
+ |
+LL | #[foo]
+ | ^^^^^^
+
+error: `#[bar]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:169:5
+ |
+LL | #[bar]
+ | ^^^^^^
+
+error: `#[bar = ...]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:181:5
+ |
+LL | #[bar = "..."]
+ | ^^^^^^^^^^^^^^
+
+error: `#[bar = ...]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:193:5
+ |
+LL | #[bar = 4]
+ | ^^^^^^^^^^
+
+error: `#[bar("...")]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:205:11
+ |
+LL | #[bar("...")]
+ | ^^^^^
+ |
+ = help: first argument of the attribute should be the diagnostic slug
+
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+ --> $DIR/subdiagnostic-derive.rs:217:5
+ |
+LL | #[label(code = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: subdiagnostic kind not specified
+ --> $DIR/subdiagnostic-derive.rs:234:5
+ |
+LL | B {
+ | ^
+
+error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
+ --> $DIR/subdiagnostic-derive.rs:246:5
+ |
+LL | #[primary_span]
+ | ^^^^^^^^^^^^^^^
+
+error: label without `#[primary_span]` field
+ --> $DIR/subdiagnostic-derive.rs:243:1
+ |
+LL | / #[label(parser::add_paren)]
+LL | |
+LL | | struct W {
+LL | | #[primary_span]
+LL | |
+LL | | span: String,
+LL | | }
+ | |_^
+
+error: `#[applicability]` is only valid on suggestions
+ --> $DIR/subdiagnostic-derive.rs:256:5
+ |
+LL | #[applicability]
+ | ^^^^^^^^^^^^^^^^
+
+error: `#[bar]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:266:5
+ |
+LL | #[bar]
+ | ^^^^^^
+ |
+ = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
+
+error: `#[bar = ...]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:277:5
+ |
+LL | #[bar = "..."]
+ | ^^^^^^^^^^^^^^
+
+error: `#[bar(...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:288:5
+ |
+LL | #[bar("...")]
+ | ^^^^^^^^^^^^^
+
+error: unexpected unsupported untagged union
+ --> $DIR/subdiagnostic-derive.rs:304:1
+ |
+LL | / union AC {
+LL | |
+LL | | span: u32,
+LL | | b: u64
+LL | | }
+ | |_^
+
+error: specified multiple times
+ --> $DIR/subdiagnostic-derive.rs:314:1
+ |
+LL | #[label(parser::add_paren)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/subdiagnostic-derive.rs:311:1
+ |
+LL | #[label(parser::add_paren)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: specified multiple times
+ --> $DIR/subdiagnostic-derive.rs:314:1
+ |
+LL | #[label(parser::add_paren)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/subdiagnostic-derive.rs:311:1
+ |
+LL | #[label(parser::add_paren)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[label(parser::add_paren)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:323:28
+ |
+LL | #[label(parser::add_paren, parser::add_paren)]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: a diagnostic slug must be the first argument to the attribute
+
+error: specified multiple times
+ --> $DIR/subdiagnostic-derive.rs:336:5
+ |
+LL | #[primary_span]
+ | ^^^^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/subdiagnostic-derive.rs:333:5
+ |
+LL | #[primary_span]
+ | ^^^^^^^^^^^^^^^
+
+error: subdiagnostic kind not specified
+ --> $DIR/subdiagnostic-derive.rs:342:8
+ |
+LL | struct AG {
+ | ^^
+
+error: specified multiple times
+ --> $DIR/subdiagnostic-derive.rs:379:47
+ |
+LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
+ | ^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/subdiagnostic-derive.rs:379:33
+ |
+LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
+ | ^^^^^^^^^^^^
+
+error: specified multiple times
+ --> $DIR/subdiagnostic-derive.rs:397:5
+ |
+LL | #[applicability]
+ | ^^^^^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/subdiagnostic-derive.rs:394:5
+ |
+LL | #[applicability]
+ | ^^^^^^^^^^^^^^^^
+
+error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
+ --> $DIR/subdiagnostic-derive.rs:408:5
+ |
+LL | #[applicability]
+ | ^^^^^^^^^^^^^^^^
+
+error: suggestion without `applicability`
+ --> $DIR/subdiagnostic-derive.rs:403:1
+ |
+LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | |
+LL | | struct AL {
+LL | | #[primary_span]
+... |
+LL | | applicability: Span,
+LL | | }
+ | |_^
+
+error: suggestion without `applicability`
+ --> $DIR/subdiagnostic-derive.rs:414:1
+ |
+LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | |
+LL | | struct AM {
+LL | | #[primary_span]
+LL | | span: Span,
+LL | | }
+ | |_^
+
+error: suggestion without `code = "..."`
+ --> $DIR/subdiagnostic-derive.rs:422:1
+ |
+LL | / #[suggestion(parser::add_paren)]
+LL | |
+LL | | struct AN {
+LL | | #[primary_span]
+... |
+LL | | applicability: Applicability,
+LL | | }
+ | |_^
+
+error: invalid applicability
+ --> $DIR/subdiagnostic-derive.rs:432:46
+ |
+LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: suggestion without `applicability`
+ --> $DIR/subdiagnostic-derive.rs:450:1
+ |
+LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | |
+LL | |
+LL | | struct AR {
+LL | | var: String,
+LL | | }
+ | |_^
+
+error: suggestion without `#[primary_span]` field
+ --> $DIR/subdiagnostic-derive.rs:450:1
+ |
+LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | |
+LL | |
+LL | | struct AR {
+LL | | var: String,
+LL | | }
+ | |_^
+
+error: unsupported type attribute for subdiagnostic enum
+ --> $DIR/subdiagnostic-derive.rs:465:1
+ |
+LL | #[label]
+ | ^^^^^^^^
+
+error: `var` doesn't refer to a field on this type
+ --> $DIR/subdiagnostic-derive.rs:485:39
+ |
+LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
+
+error: `var` doesn't refer to a field on this type
+ --> $DIR/subdiagnostic-derive.rs:504:43
+ |
+LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
+
+error: cannot find attribute `foo` in this scope
+ --> $DIR/subdiagnostic-derive.rs:63:3
+ |
+LL | #[foo]
+ | ^^^
+
+error: cannot find attribute `foo` in this scope
+ --> $DIR/subdiagnostic-derive.rs:155:3
+ |
+LL | #[foo]
+ | ^^^
+
+error: cannot find attribute `bar` in this scope
+ --> $DIR/subdiagnostic-derive.rs:169:7
+ |
+LL | #[bar]
+ | ^^^
+
+error: cannot find attribute `bar` in this scope
+ --> $DIR/subdiagnostic-derive.rs:181:7
+ |
+LL | #[bar = "..."]
+ | ^^^
+
+error: cannot find attribute `bar` in this scope
+ --> $DIR/subdiagnostic-derive.rs:193:7
+ |
+LL | #[bar = 4]
+ | ^^^
+
+error: cannot find attribute `bar` in this scope
+ --> $DIR/subdiagnostic-derive.rs:205:7
+ |
+LL | #[bar("...")]
+ | ^^^
+
+error: cannot find attribute `bar` in this scope
+ --> $DIR/subdiagnostic-derive.rs:266:7
+ |
+LL | #[bar]
+ | ^^^
+
+error: cannot find attribute `bar` in this scope
+ --> $DIR/subdiagnostic-derive.rs:277:7
+ |
+LL | #[bar = "..."]
+ | ^^^
+
+error: cannot find attribute `bar` in this scope
+ --> $DIR/subdiagnostic-derive.rs:288:7
+ |
+LL | #[bar("...")]
+ | ^^^
+
+error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
+ --> $DIR/subdiagnostic-derive.rs:118:9
+ |
+LL | #[label(slug)]
+ | ^^^^ not found in `rustc_errors::fluent`
+
+error: aborting due to 52 previous errors
+
+For more information about this error, try `rustc --explain E0425`.