From 99bc97940314176bc6ed38cea11723cc1fd9ee3b Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 23 Jun 2022 14:51:44 +0100 Subject: macros: use typed identifiers in diag derive Using typed identifiers instead of strings with the Fluent identifier enables the diagnostic derive to benefit from the compile-time validation that comes with typed identifiers - use of a non-existent Fluent identifier will not compile. Signed-off-by: David Wood --- src/test/ui-fulldeps/internal-lints/diagnostics.rs | 2 +- .../session-diagnostic/diagnostic-derive.rs | 239 +++++++++-------- .../session-diagnostic/diagnostic-derive.stderr | 287 ++++++++++++--------- 3 files changed, 309 insertions(+), 219 deletions(-) (limited to 'src') diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs index 817d8531da9..3e349ab0258 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(slug = "parser-expect-path")] +#[error(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 84d5de17309..8cbee4c6d92 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -26,15 +26,15 @@ use rustc_errors::Applicability; extern crate rustc_session; #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "hello-world")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct Hello {} #[derive(SessionDiagnostic)] -#[warning(code = "E0123", slug = "hello-world")] +#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")] struct HelloWarn {} #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] //~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs enum SessionDiagnosticOnEnum { Foo, @@ -42,13 +42,13 @@ enum SessionDiagnosticOnEnum { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] #[error = "E0123"] //~^ ERROR `#[error = ...]` is not a valid attribute struct WrongStructAttrStyle {} #[derive(SessionDiagnostic)] -#[nonsense(code = "E0123", slug = "foo")] +#[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 @@ -57,31 +57,39 @@ struct InvalidStructAttr {} #[derive(SessionDiagnostic)] #[error("E0123")] //~^ ERROR `#[error("...")]` is not a valid attribute -//~^^ ERROR `slug` not specified +//~^^ ERROR diagnostic slug not specified struct InvalidLitNestedAttr {} #[derive(SessionDiagnostic)] -#[error(nonsense, code = "E0123", slug = "foo")] -//~^ ERROR `#[error(nonsense)]` is not a valid attribute +#[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(code = "E0123", slug = "foo")] +#[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 @@ -89,44 +97,45 @@ struct WrongPlaceField { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] -#[error(code = "E0456", slug = "bar")] +#[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(code = "E0123", slug = "foo")] -#[warning(code = "E0293", slug = "bar")] +#[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(code = "E0456", code = "E0457", slug = "bar")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] //~^ ERROR specified multiple times struct CodeSpecifiedTwice {} #[derive(SessionDiagnostic)] -#[error(code = "E0456", slug = "foo", slug = "bar")] -//~^ ERROR specified multiple times +#[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 `slug` not specified +#[error(code = "E0456")] +//~^ ERROR diagnostic slug not specified struct SlugNotProvided {} #[derive(SessionDiagnostic)] -#[error(slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound)] struct CodeNotProvided {} #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct MessageWrongType { #[primary_span] //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` @@ -134,7 +143,7 @@ struct MessageWrongType { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct InvalidPathFieldAttr { #[nonsense] //~^ ERROR `#[nonsense]` is not a valid attribute @@ -143,34 +152,34 @@ struct InvalidPathFieldAttr { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithField { name: String, - #[label = "bar"] + #[label(typeck::label)] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithMessageAppliedToField { - #[label = "bar"] - //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span` + #[label(typeck::label)] + //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` name: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithNonexistentField { - #[suggestion(message = "bar", code = "{name}")] + #[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(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorMissingClosingBrace { - #[suggestion(message = "bar", code = "{name")] + #[suggestion(typeck::suggestion, code = "{name")] suggestion: (Span, Applicability), name: String, val: usize, @@ -178,48 +187,48 @@ struct ErrorMissingClosingBrace { #[derive(SessionDiagnostic)] //~^ ERROR invalid format string: unmatched `}` -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorMissingOpeningBrace { - #[suggestion(message = "bar", code = "name}")] + #[suggestion(typeck::suggestion, code = "name}")] suggestion: (Span, Applicability), name: String, val: usize, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelOnSpan { - #[label = "bar"] + #[label(typeck::label)] sp: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelOnNonSpan { - #[label = "bar"] - //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span` + #[label(typeck::label)] + //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` id: u32, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct Suggest { - #[suggestion(message = "bar", code = "This is the suggested code")] - #[suggestion_short(message = "qux", code = "This is the suggested code")] - #[suggestion_hidden(message = "foobar", code = "This is the suggested code")] - #[suggestion_verbose(message = "fooqux", code = "This is the suggested code")] + #[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(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithoutCode { - #[suggestion(message = "bar")] + #[suggestion(typeck::suggestion)] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithBadKey { #[suggestion(nonsense = "bar")] //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute @@ -227,7 +236,7 @@ struct SuggestWithBadKey { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithShorthandMsg { #[suggestion(msg = "bar")] //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute @@ -235,91 +244,91 @@ struct SuggestWithShorthandMsg { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithoutMsg { #[suggestion(code = "bar")] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithTypesSwapped { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] suggestion: (Applicability, Span), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithWrongTypeApplicabilityOnly { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] //~^ ERROR wrong field type for suggestion suggestion: Applicability, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithSpanOnly { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] suggestion: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateSpanAndApplicability { - #[suggestion(message = "bar", code = "This is suggested code")] + #[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(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateApplicabilityAndSpan { - #[suggestion(message = "bar", code = "This is suggested code")] + #[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(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct WrongKindOfAnnotation { - #[label("bar")] - //~^ ERROR `#[label(...)]` is not a valid attribute + #[label = "bar"] + //~^ ERROR `#[label = ...]` is not a valid attribute z: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct OptionsInErrors { - #[label = "bar"] + #[label(typeck::label)] label: Option, - #[suggestion(message = "bar")] + #[suggestion(typeck::suggestion)] opt_sugg: Option<(Span, Applicability)>, } #[derive(SessionDiagnostic)] -#[error(code = "E0456", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0456")] struct MoveOutOfBorrowError<'tcx> { name: Ident, ty: Ty<'tcx>, #[primary_span] - #[label = "bar"] + #[label(typeck::label)] span: Span, - #[label = "qux"] + #[label(typeck::label)] other_span: Span, - #[suggestion(message = "bar", code = "{name}.clone()")] + #[suggestion(typeck::suggestion, code = "{name}.clone()")] opt_sugg: Option<(Span, Applicability)>, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithLifetime<'a> { - #[label = "bar"] + #[label(typeck::label)] span: Span, name: &'a str, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithDefaultLabelAttr<'a> { #[label] span: Span, @@ -328,7 +337,7 @@ struct ErrorWithDefaultLabelAttr<'a> { #[derive(SessionDiagnostic)] //~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ArgFieldWithoutSkip { #[primary_span] span: Span, @@ -336,7 +345,7 @@ struct ArgFieldWithoutSkip { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ArgFieldWithSkip { #[primary_span] span: Span, @@ -347,116 +356,116 @@ struct ArgFieldWithSkip { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedNote { #[note] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedNoteCustom { - #[note = "bar"] + #[note(typeck::note)] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] #[note] struct ErrorWithNote { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] -#[note = "bar"] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[note(typeck::note)] struct ErrorWithNoteCustom { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedHelp { #[help] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedHelpCustom { - #[help = "bar"] + #[help(typeck::help)] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] #[help] struct ErrorWithHelp { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] -#[help = "bar"] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[help(typeck::help)] struct ErrorWithHelpCustom { val: String, } #[derive(SessionDiagnostic)] #[help] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithHelpWrongOrder { val: String, } #[derive(SessionDiagnostic)] -#[help = "bar"] -#[error(code = "E0123", slug = "foo")] +#[help(typeck::help)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithHelpCustomWrongOrder { val: String, } #[derive(SessionDiagnostic)] #[note] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithNoteWrongOrder { val: String, } #[derive(SessionDiagnostic)] -#[note = "bar"] -#[error(code = "E0123", slug = "foo")] +#[note(typeck::note)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithNoteCustomWrongOrder { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ApplicabilityInBoth { - #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")] + #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] //~^ ERROR applicability cannot be set in both the field and attribute suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct InvalidApplicability { - #[suggestion(message = "bar", code = "...", applicability = "batman")] + #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] //~^ ERROR invalid applicability suggestion: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ValidApplicability { - #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")] + #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] suggestion: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct NoApplicability { - #[suggestion(message = "bar", code = "...")] + #[suggestion(typeck::suggestion, code = "...")] suggestion: Span, } @@ -465,14 +474,14 @@ struct NoApplicability { struct Note; #[derive(SessionDiagnostic)] -#[error(slug = "subdiagnostic")] +#[error(typeck::ambiguous_lifetime_bound)] struct Subdiagnostic { #[subdiagnostic] note: Note, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct VecField { #[primary_span] #[label] @@ -480,23 +489,47 @@ struct VecField { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct UnitField { #[primary_span] spans: Span, #[help] foo: (), - #[help = "a"] + #[help(typeck::help)] bar: (), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct OptUnitField { #[primary_span] spans: Span, #[help] foo: Option<()>, - #[help = "a"] + #[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, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 85ea44ec278..0d9690e1f5a 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:37:1 | -LL | / #[error(code = "E0123", slug = "foo")] +LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | LL | | enum SessionDiagnosticOnEnum { LL | | Foo, @@ -18,15 +18,15 @@ LL | #[error = "E0123"] error: `#[nonsense(...)]` is not a valid attribute --> $DIR/diagnostic-derive.rs:51:1 | -LL | #[nonsense(code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: only `error` and `warning` are valid attributes + = help: only `error`, `warning`, `help` and `note` are valid attributes error: diagnostic kind not specified --> $DIR/diagnostic-derive.rs:51:1 | -LL | / #[nonsense(code = "E0123", slug = "foo")] +LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | LL | | LL | | @@ -40,8 +40,10 @@ error: `#[error("...")]` is not a valid attribute | LL | #[error("E0123")] | ^^^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug -error: `slug` not specified +error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:58:1 | LL | / #[error("E0123")] @@ -50,183 +52,215 @@ LL | | LL | | struct InvalidLitNestedAttr {} | |______________________________^ | - = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug - -error: `#[error(nonsense)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:64:9 - | -LL | #[error(nonsense, code = "E0123", slug = "foo")] - | ^^^^^^^^ + = 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:69: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:69: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:74:9 + --> $DIR/diagnostic-derive.rs:75:9 | LL | #[error(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: only `slug` and `code` are valid nested attributes + = help: first argument of the attribute should be the diagnostic slug + +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:75: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:79:9 + --> $DIR/diagnostic-derive.rs:81:9 | LL | #[error(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug -error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:86:5 +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:81:1 | -LL | #[suggestion = "bar"] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | / #[error(nonsense = 4, code = "E0123", slug = "foo")] +LL | | +LL | | +LL | | struct InvalidNestedStructAttr3 {} + | |__________________________________^ | - = help: only `label`, `note` and `help` are valid field attributes + = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` -error: specified multiple times - --> $DIR/diagnostic-derive.rs:93:1 +error: `#[error(slug = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:87:59 | -LL | #[error(code = "E0456", slug = "bar")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^ | -note: previously specified here - --> $DIR/diagnostic-derive.rs:92:1 + = help: only `code` is a valid nested attributes following the slug + +error: `#[suggestion = ...]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:94:5 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion = "bar"] + | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:93:16 + --> $DIR/diagnostic-derive.rs:101:1 | -LL | #[error(code = "E0456", slug = "bar")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:92:16 + --> $DIR/diagnostic-derive.rs:100:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:93:32 + --> $DIR/diagnostic-derive.rs:101:1 | -LL | #[error(code = "E0456", slug = "bar")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:92:32 + --> $DIR/diagnostic-derive.rs:100:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:1 + --> $DIR/diagnostic-derive.rs:101:50 | -LL | #[warning(code = "E0293", slug = "bar")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:1 + --> $DIR/diagnostic-derive.rs:100:50 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:18 + --> $DIR/diagnostic-derive.rs:109:1 | -LL | #[warning(code = "E0293", slug = "bar")] - | ^^^^^^^ +LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:16 + --> $DIR/diagnostic-derive.rs:108:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:34 + --> $DIR/diagnostic-derive.rs:109:1 | -LL | #[warning(code = "E0293", slug = "bar")] - | ^^^^^ +LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:32 + --> $DIR/diagnostic-derive.rs:108:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:108:32 + --> $DIR/diagnostic-derive.rs:109:52 | -LL | #[error(code = "E0456", code = "E0457", slug = "bar")] - | ^^^^^^^ +LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] + | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:16 + --> $DIR/diagnostic-derive.rs:108:50 | -LL | #[error(code = "E0456", code = "E0457", slug = "bar")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:113:46 + --> $DIR/diagnostic-derive.rs:116:66 | -LL | #[error(code = "E0456", slug = "foo", slug = "bar")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] + | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:113:32 + --> $DIR/diagnostic-derive.rs:116:50 | -LL | #[error(code = "E0456", slug = "foo", slug = "bar")] - | ^^^^^ +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:121:43 + | +LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic kind not specified - --> $DIR/diagnostic-derive.rs:118:1 + --> $DIR/diagnostic-derive.rs:126:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use the `#[error(...)]` attribute to create an error -error: `slug` not specified - --> $DIR/diagnostic-derive.rs:121:1 +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:129:1 | LL | / #[error(code = "E0456")] +LL | | LL | | struct SlugNotProvided {} | |_________________________^ | - = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug + = 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` - --> $DIR/diagnostic-derive.rs:131:5 + --> $DIR/diagnostic-derive.rs:140:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:139:5 + --> $DIR/diagnostic-derive.rs:148: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` - --> $DIR/diagnostic-derive.rs:156:5 +error: the `#[label(...)]` attribute can only be applied to fields of type `Span` + --> $DIR/diagnostic-derive.rs:165:5 | -LL | #[label = "bar"] - | ^^^^^^^^^^^^^^^^ +LL | #[label(typeck::label)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:164:42 + --> $DIR/diagnostic-derive.rs:173:45 | -LL | #[suggestion(message = "bar", code = "{name}")] - | ^^^^^^^^ +LL | #[suggestion(typeck::suggestion, code = "{name}")] + | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:169:16 + --> $DIR/diagnostic-derive.rs:178:16 | LL | #[derive(SessionDiagnostic)] | - ^ expected `'}'` in format string @@ -237,7 +271,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:179:15 + --> $DIR/diagnostic-derive.rs:188:15 | LL | #[derive(SessionDiagnostic)] | ^ unmatched `}` in format string @@ -245,14 +279,14 @@ LL | #[derive(SessionDiagnostic)] = 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` - --> $DIR/diagnostic-derive.rs:199:5 +error: the `#[label(...)]` attribute can only be applied to fields of type `Span` + --> $DIR/diagnostic-derive.rs:208:5 | -LL | #[label = "bar"] - | ^^^^^^^^^^^^^^^^ +LL | #[label(typeck::label)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:224:18 + --> $DIR/diagnostic-derive.rs:233:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^ @@ -260,7 +294,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:232:18 + --> $DIR/diagnostic-derive.rs:241:18 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^ @@ -268,9 +302,9 @@ LL | #[suggestion(msg = "bar")] = help: only `message`, `code` and `applicability` are valid field attributes error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:254:5 + --> $DIR/diagnostic-derive.rs:263:5 | -LL | / #[suggestion(message = "bar", code = "This is suggested code")] +LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | LL | | suggestion: Applicability, | |_____________________________^ @@ -278,55 +312,77 @@ 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:269:5 + --> $DIR/diagnostic-derive.rs:278:5 | -LL | / #[suggestion(message = "bar", code = "This is suggested code")] +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:277:5 + --> $DIR/diagnostic-derive.rs:286:5 | -LL | / #[suggestion(message = "bar", code = "This is suggested code")] +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:285:5 - | -LL | #[label("bar")] - | ^^^^^^^^^^^^^^^ +error: `#[label = ...]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:294:5 | - = help: only `suggestion{,_short,_hidden,_verbose}` are valid field attributes +LL | #[label = "bar"] + | ^^^^^^^^^^^^^^^^ error: applicability cannot be set in both the field and attribute - --> $DIR/diagnostic-derive.rs:436:49 + --> $DIR/diagnostic-derive.rs:445:52 | -LL | #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:444:49 + --> $DIR/diagnostic-derive.rs:453:52 + | +LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[label(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:516:5 + | +LL | #[label(typeck::label, foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[label(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:524:5 + | +LL | #[label(typeck::label, foo = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[label(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:532:5 | -LL | #[suggestion(message = "bar", code = "...", applicability = "batman")] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(typeck::label, foo("..."))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:51:3 | -LL | #[nonsense(code = "E0123", slug = "foo")] +LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:139:7 + --> $DIR/diagnostic-derive.rs:148:7 | LL | #[nonsense] | ^^^^^^^^ +error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent` + --> $DIR/diagnostic-derive.rs:64: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:329:10 + --> $DIR/diagnostic-derive.rs:338:10 | LL | #[derive(SessionDiagnostic)] | ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` @@ -345,6 +401,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 39 previous errors +error: aborting due to 46 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From abd3467d47ad8f366239100334c31478f075a0de Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 23 Jun 2022 16:12:52 +0100 Subject: macros: use typed identifiers in subdiag derive As in the diagnostic derive, using typed identifiers in the subdiagnostic derive improves the diagnostics of using the subdiagnostic derive as Fluent messages will be confirmed to exist at compile-time. Signed-off-by: David Wood --- compiler/rustc_error_messages/src/lib.rs | 21 +++ compiler/rustc_macros/src/diagnostics/mod.rs | 6 +- .../rustc_macros/src/diagnostics/subdiagnostic.rs | 84 +++++++-- compiler/rustc_parse/src/parser/diagnostics.rs | 6 +- compiler/rustc_typeck/src/errors.rs | 8 +- src/test/ui-fulldeps/internal-lints/diagnostics.rs | 2 +- .../session-diagnostic/diagnostic-derive.rs | 2 +- .../session-diagnostic/subdiagnostic-derive.rs | 159 ++++++++-------- .../session-diagnostic/subdiagnostic-derive.stderr | 207 +++++++++++---------- 9 files changed, 298 insertions(+), 197 deletions(-) (limited to 'src') diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 7211c054326..8d5ab1a4517 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -347,6 +347,27 @@ impl> From for DiagnosticMessage { } } +/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but +/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the +/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be +/// able to convert between these, as much as they'll be converted back into `DiagnosticMessage` +/// using `with_subdiagnostic_message` eventually. Don't use this other than for the derive. +impl Into for DiagnosticMessage { + fn into(self) -> SubdiagnosticMessage { + match self { + DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), + DiagnosticMessage::FluentIdentifier(id, None) => { + SubdiagnosticMessage::FluentIdentifier(id) + } + // There isn't really a sensible behaviour for this because it loses information but + // this is the most sensible of the behaviours. + DiagnosticMessage::FluentIdentifier(_, Some(attr)) => { + SubdiagnosticMessage::FluentAttr(attr) + } + } + } +} + /// A span together with some additional data. #[derive(Clone, Debug)] pub struct SpanLabel { diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 88182ed5a12..2eee4bfb5dd 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -72,12 +72,12 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// ```ignore (rust) /// #[derive(SessionSubdiagnostic)] /// pub enum ExpectedIdentifierLabel<'tcx> { -/// #[label(slug = "parser-expected-identifier")] +/// #[label(parser::expected_identifier)] /// WithoutFound { /// #[primary_span] /// span: Span, /// } -/// #[label(slug = "parser-expected-identifier-found")] +/// #[label(parser::expected_identifier_found)] /// WithFound { /// #[primary_span] /// span: Span, @@ -86,7 +86,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// } /// /// #[derive(SessionSubdiagnostic)] -/// #[suggestion_verbose(slug = "parser-raw-identifier")] +/// #[suggestion_verbose(parser::raw_identifier)] /// pub struct RawIdentifierSuggestion<'tcx> { /// #[primary_span] /// span: Span, diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 9aeb484bfd5..eab954a9c1b 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -13,7 +13,7 @@ use quote::{format_ident, quote}; use std::collections::HashMap; use std::fmt; use std::str::FromStr; -use syn::{spanned::Spanned, Meta, MetaList, MetaNameValue}; +use syn::{parse_quote, spanned::Spanned, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; /// Which kind of suggestion is being created? @@ -194,8 +194,8 @@ struct SessionSubdiagnosticDeriveBuilder<'a> { kind: Option<(SubdiagnosticKind, proc_macro::Span)>, /// Slug of the subdiagnostic - corresponds to the Fluent identifier for the message - from the - /// `#[kind(slug = "...")]` attribute on the type or variant. - slug: Option<(String, proc_macro::Span)>, + /// `#[kind(slug)]` attribute on the type or variant. + slug: Option<(Path, proc_macro::Span)>, /// If a suggestion, the code to suggest as a replacement - from the `#[kind(code = "...")]` /// attribute on the type or variant. code: Option<(TokenStream, proc_macro::Span)>, @@ -224,9 +224,34 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { let meta = attr.parse_meta()?; let kind = match meta { Meta::List(MetaList { ref nested, .. }) => { - for nested_attr in nested { + let mut nested_iter = nested.into_iter(); + if let Some(nested_attr) = nested_iter.next() { + match nested_attr { + NestedMeta::Meta(Meta::Path(path)) => { + self.slug.set_once((path.clone(), span)); + } + NestedMeta::Meta(meta @ Meta::NameValue(_)) + if matches!( + meta.path().segments.last().unwrap().ident.to_string().as_str(), + "code" | "applicability" + ) => + { + // don't error for valid follow-up attributes + } + nested_attr => { + throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help( + "first argument of the attribute should be the diagnostic \ + slug", + ) + }) + } + }; + } + + for nested_attr in nested_iter { let meta = match nested_attr { - syn::NestedMeta::Meta(ref meta) => meta, + NestedMeta::Meta(ref meta) => meta, _ => throw_invalid_nested_attr!(attr, &nested_attr), }; @@ -241,7 +266,6 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { let formatted_str = self.build_format(&s.value(), s.span()); self.code.set_once((formatted_str, span)); } - "slug" => self.slug.set_once((s.value(), span)), "applicability" => { let value = match Applicability::from_str(&s.value()) { Ok(v) => v, @@ -253,11 +277,23 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { self.applicability.set_once((quote! { #value }, span)); } _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("only `code`, `slug` and `applicability` are valid nested attributes") + diag.help( + "only `code` and `applicability` are valid nested \ + attributes", + ) }), } } - _ => throw_invalid_nested_attr!(attr, &nested_attr), + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + if matches!(meta, Meta::Path(_)) { + diag.help( + "a diagnostic slug must be the first argument to the \ + attribute", + ) + } else { + diag + } + }), } } @@ -281,10 +317,27 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { ); } + if matches!( + kind, + SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note + ) && self.applicability.is_some() + { + throw_span_err!( + span, + &format!( + "`applicability` is not a valid nested attribute of a `{}` attribute", + name + ) + ); + } + if self.slug.is_none() { throw_span_err!( span, - &format!("`slug` must be set in a `#[{}(...)]` attribute", name) + &format!( + "diagnostic slug must be first argument of a `#[{}(...)]` attribute", + name + ) ); } @@ -335,7 +388,10 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { return Ok(quote! {}); } _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `primary_span`, `applicability` and `skip_arg` are valid field attributes") + diag.help( + "only `primary_span`, `applicability` and `skip_arg` are valid field \ + attributes", + ) }), }, _ => throw_invalid_attr!(attr, &meta), @@ -375,7 +431,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { } // Missing slug errors will already have been reported. - let slug = self.slug.as_ref().map(|(slug, _)| &**slug).unwrap_or("missing-slug"); + let slug = self + .slug + .as_ref() + .map(|(slug, _)| slug.clone()) + .unwrap_or_else(|| parse_quote! { you::need::to::specify::a::slug }); let code = match self.code.as_ref() { Some((code, _)) => Some(quote! { #code }), None if is_suggestion => { @@ -397,7 +457,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { let diag = &self.diag; let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); - let message = quote! { rustc_errors::SubdiagnosticMessage::message(#slug) }; + let message = quote! { rustc_errors::fluent::#slug }; let call = if matches!(kind, SubdiagnosticKind::Suggestion(..)) { if let Some(span) = span_field { quote! { #diag.#name(#span, #message, #code, #applicability); } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 30869f055f5..58d5d43cfbf 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -265,7 +265,7 @@ struct BadTypePlus { #[derive(SessionSubdiagnostic)] pub enum BadTypePlusSub { #[suggestion( - slug = "parser-add-paren", + parser::add_paren, code = "{sum_with_parens}", applicability = "machine-applicable" )] @@ -274,12 +274,12 @@ pub enum BadTypePlusSub { #[primary_span] span: Span, }, - #[label(slug = "parser-forgot-paren")] + #[label(parser::forgot_paren)] ForgotParen { #[primary_span] span: Span, }, - #[label(slug = "parser-expect-path")] + #[label(parser::expect_path)] ExpectPath { #[primary_span] span: Span, diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 758108e5d71..4cdec615d82 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -197,7 +197,7 @@ pub struct AddressOfTemporaryTaken { #[derive(SessionSubdiagnostic)] pub enum AddReturnTypeSuggestion<'tcx> { #[suggestion( - slug = "typeck-add-return-type-add", + typeck::add_return_type_add, code = "-> {found} ", applicability = "machine-applicable" )] @@ -207,7 +207,7 @@ pub enum AddReturnTypeSuggestion<'tcx> { found: Ty<'tcx>, }, #[suggestion( - slug = "typeck-add-return-type-missing-here", + typeck::add_return_type_missing_here, code = "-> _ ", applicability = "has-placeholders" )] @@ -219,12 +219,12 @@ pub enum AddReturnTypeSuggestion<'tcx> { #[derive(SessionSubdiagnostic)] pub enum ExpectedReturnTypeLabel<'tcx> { - #[label(slug = "typeck-expected-default-return-type")] + #[label(typeck::expected_default_return_type)] Unit { #[primary_span] span: Span, }, - #[label(slug = "typeck-expected-return-type")] + #[label(typeck::expected_return_type)] Other { #[primary_span] span: Span, diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs index 3e349ab0258..d6f63d44ba6 100644 --- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs +++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs @@ -23,7 +23,7 @@ struct DeriveSessionDiagnostic { } #[derive(SessionSubdiagnostic)] -#[note(slug = "note")] +#[note(parser::add_paren)] struct Note { #[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 8cbee4c6d92..7bec1897fa5 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -470,7 +470,7 @@ struct NoApplicability { } #[derive(SessionSubdiagnostic)] -#[note(slug = "note")] +#[note(parser::add_paren)] struct Note; #[derive(SessionDiagnostic)] diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index bb406c35c0e..6f4b6105b3e 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -20,7 +20,7 @@ use rustc_span::Span; use rustc_macros::SessionSubdiagnostic; #[derive(SessionSubdiagnostic)] -#[label(slug = "label-a")] +#[label(parser::add_paren)] struct A { #[primary_span] span: Span, @@ -29,13 +29,13 @@ struct A { #[derive(SessionSubdiagnostic)] enum B { - #[label(slug = "label-b-a")] + #[label(parser::add_paren)] A { #[primary_span] span: Span, var: String, }, - #[label(slug = "label-b-b")] + #[label(parser::add_paren)] B { #[primary_span] span: Span, @@ -44,7 +44,7 @@ enum B { } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-c")] +#[label(parser::add_paren)] //~^ ERROR label without `#[primary_span]` field struct C { var: String, @@ -116,7 +116,8 @@ struct K { #[derive(SessionSubdiagnostic)] #[label(slug)] -//~^ ERROR `#[label(slug)]` is not a valid attribute +//~^ ERROR cannot find value `slug` in module `rustc_errors::fluent` +//~^^ NOTE not found in `rustc_errors::fluent` struct L { #[primary_span] span: Span, @@ -125,7 +126,7 @@ struct L { #[derive(SessionSubdiagnostic)] #[label()] -//~^ ERROR `slug` must be set in a `#[label(...)]` attribute +//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute struct M { #[primary_span] span: Span, @@ -133,7 +134,7 @@ struct M { } #[derive(SessionSubdiagnostic)] -#[label(code = "...")] +#[label(parser::add_paren, code = "...")] //~^ ERROR `code` is not a valid nested attribute of a `label` attribute struct N { #[primary_span] @@ -141,12 +142,21 @@ struct N { 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 O { - #[label(slug = "...")] +enum P { + #[label(parser::add_paren)] A { #[primary_span] span: Span, @@ -155,7 +165,7 @@ enum O { } #[derive(SessionSubdiagnostic)] -enum P { +enum Q { #[bar] //~^ ERROR `#[bar]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -167,7 +177,7 @@ enum P { } #[derive(SessionSubdiagnostic)] -enum Q { +enum R { #[bar = "..."] //~^ ERROR `#[bar = ...]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -179,7 +189,7 @@ enum Q { } #[derive(SessionSubdiagnostic)] -enum R { +enum S { #[bar = 4] //~^ ERROR `#[bar = ...]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -191,7 +201,7 @@ enum R { } #[derive(SessionSubdiagnostic)] -enum S { +enum T { #[bar("...")] //~^ ERROR `#[bar("...")]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -203,9 +213,9 @@ enum S { } #[derive(SessionSubdiagnostic)] -enum T { +enum U { #[label(code = "...")] -//~^ ERROR `code` is not a valid nested attribute of a `label` +//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute A { #[primary_span] span: Span, @@ -214,8 +224,8 @@ enum T { } #[derive(SessionSubdiagnostic)] -enum U { - #[label(slug = "label-u")] +enum V { + #[label(parser::add_paren)] A { #[primary_span] span: Span, @@ -230,17 +240,17 @@ enum U { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] +#[label(parser::add_paren)] //~^ ERROR label without `#[primary_span]` field -struct V { +struct W { #[primary_span] //~^ ERROR the `#[primary_span]` attribute can only be applied to fields of type `Span` span: String, } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct W { +#[label(parser::add_paren)] +struct X { #[primary_span] span: Span, #[applicability] @@ -249,8 +259,8 @@ struct W { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct X { +#[label(parser::add_paren)] +struct Y { #[primary_span] span: Span, #[bar] @@ -260,8 +270,8 @@ struct X { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct Y { +#[label(parser::add_paren)] +struct Z { #[primary_span] span: Span, #[bar = "..."] @@ -271,8 +281,8 @@ struct Y { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct Z { +#[label(parser::add_paren)] +struct AA { #[primary_span] span: Span, #[bar("...")] @@ -282,8 +292,8 @@ struct Z { } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-aa")] -struct AA { +#[label(parser::add_paren)] +struct AB { #[primary_span] span: Span, #[skip_arg] @@ -291,36 +301,35 @@ struct AA { } #[derive(SessionSubdiagnostic)] -union AB { +union AC { //~^ ERROR unexpected unsupported untagged union span: u32, b: u64 } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-ac-1")] +#[label(parser::add_paren)] //~^ NOTE previously specified here //~^^ NOTE previously specified here -#[label(slug = "label-ac-2")] +#[label(parser::add_paren)] //~^ ERROR specified multiple times //~^^ ERROR specified multiple times -struct AC { +struct AD { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-ad-1", slug = "label-ad-2")] -//~^ ERROR specified multiple times -//~^^ NOTE previously specified here -struct AD { +#[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(slug = "label-ad-1")] -struct AE { +#[label(parser::add_paren)] +struct AF { #[primary_span] //~^ NOTE previously specified here span_a: Span, @@ -330,15 +339,15 @@ struct AE { } #[derive(SessionSubdiagnostic)] -struct AF { +struct AG { //~^ ERROR subdiagnostic kind not specified #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "suggestion-af", code = "...")] -struct AG { +#[suggestion(parser::add_paren, code = "...")] +struct AH { #[primary_span] span: Span, #[applicability] @@ -347,8 +356,8 @@ struct AG { } #[derive(SessionSubdiagnostic)] -enum AH { - #[suggestion(slug = "suggestion-ag-a", code = "...")] +enum AI { + #[suggestion(parser::add_paren, code = "...")] A { #[primary_span] span: Span, @@ -356,7 +365,7 @@ enum AH { applicability: Applicability, var: String, }, - #[suggestion(slug = "suggestion-ag-b", code = "...")] + #[suggestion(parser::add_paren, code = "...")] B { #[primary_span] span: Span, @@ -367,10 +376,10 @@ enum AH { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...", code = "...")] //~^ ERROR specified multiple times //~^^ NOTE previously specified here -struct AI { +struct AJ { #[primary_span] span: Span, #[applicability] @@ -378,8 +387,8 @@ struct AI { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] -struct AJ { +#[suggestion(parser::add_paren, code = "...")] +struct AK { #[primary_span] span: Span, #[applicability] @@ -391,9 +400,9 @@ struct AJ { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...")] //~^ ERROR suggestion without `applicability` -struct AK { +struct AL { #[primary_span] span: Span, #[applicability] @@ -402,17 +411,17 @@ struct AK { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...")] //~^ ERROR suggestion without `applicability` -struct AL { +struct AM { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...")] +#[suggestion(parser::add_paren)] //~^ ERROR suggestion without `code = "..."` -struct AM { +struct AN { #[primary_span] span: Span, #[applicability] @@ -420,34 +429,34 @@ struct AM { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="...", applicability = "foo")] +#[suggestion(parser::add_paren, code ="...", applicability = "foo")] //~^ ERROR invalid applicability -struct AN { +struct AO { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[help(slug = "label-am")] -struct AO { +#[help(parser::add_paren)] +struct AP { var: String } #[derive(SessionSubdiagnostic)] -#[note(slug = "label-an")] -struct AP; +#[note(parser::add_paren)] +struct AQ; #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...")] //~^ ERROR suggestion without `applicability` //~^^ ERROR suggestion without `#[primary_span]` field -struct AQ { +struct AR { var: String, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="...", applicability = "machine-applicable")] -struct AR { +#[suggestion(parser::add_paren, code ="...", applicability = "machine-applicable")] +struct AS { #[primary_span] span: Span, } @@ -455,8 +464,8 @@ struct AR { #[derive(SessionSubdiagnostic)] #[label] //~^ ERROR unsupported type attribute for subdiagnostic enum -enum AS { - #[label(slug = "...")] +enum AT { + #[label(parser::add_paren)] A { #[primary_span] span: Span, @@ -465,24 +474,24 @@ enum AS { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] -struct AT { +#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] +struct AU { #[primary_span] span: Span, var: String, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] +#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] //~^ ERROR `var` doesn't refer to a field on this type -struct AU { +struct AV { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -enum AV { - #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] +enum AW { + #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] A { #[primary_span] span: Span, @@ -491,8 +500,8 @@ enum AV { } #[derive(SessionSubdiagnostic)] -enum AW { - #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] +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] diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 4984cc4b318..f833bd210f7 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -1,7 +1,7 @@ error: label without `#[primary_span]` field --> $DIR/subdiagnostic-derive.rs:47:1 | -LL | / #[label(slug = "label-c")] +LL | / #[label(parser::add_paren)] LL | | LL | | struct C { LL | | var: String, @@ -32,98 +32,106 @@ error: `#[label(bug = ...)]` is not a valid attribute LL | #[label(bug = "...")] | ^^^^^^^^^^^ | - = help: only `code`, `slug` and `applicability` are valid nested attributes + = 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("..."))] | ^^^^^^^^^^^ - -error: `#[label(slug)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:118:9 | -LL | #[label(slug)] - | ^^^^ + = help: first argument of the attribute should be the diagnostic slug -error: `slug` must be set in a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:127:1 +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:136:1 + --> $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(code = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren, applicability = "machine-applicable")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:145:1 + --> $DIR/subdiagnostic-derive.rs:155:1 | LL | #[foo] | ^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:159:5 + --> $DIR/subdiagnostic-derive.rs:169:5 | LL | #[bar] | ^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:171:5 + --> $DIR/subdiagnostic-derive.rs:181:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:183:5 + --> $DIR/subdiagnostic-derive.rs:193:5 | LL | #[bar = 4] | ^^^^^^^^^^ error: `#[bar("...")]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:195:11 + --> $DIR/subdiagnostic-derive.rs:205:11 | LL | #[bar("...")] | ^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug -error: `code` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:207:5 +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:224:5 + --> $DIR/subdiagnostic-derive.rs:234:5 | LL | B { | ^ error: the `#[primary_span]` attribute can only be applied to fields of type `Span` - --> $DIR/subdiagnostic-derive.rs:236:5 + --> $DIR/subdiagnostic-derive.rs:246:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:233:1 + --> $DIR/subdiagnostic-derive.rs:243:1 | -LL | / #[label(slug = "...")] +LL | / #[label(parser::add_paren)] LL | | -LL | | struct V { +LL | | struct W { LL | | #[primary_span] LL | | LL | | span: String, @@ -131,13 +139,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:246:5 + --> $DIR/subdiagnostic-derive.rs:256:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:256:5 + --> $DIR/subdiagnostic-derive.rs:266:5 | LL | #[bar] | ^^^^^^ @@ -145,21 +153,21 @@ 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:267:5 + --> $DIR/subdiagnostic-derive.rs:277:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:278:5 + --> $DIR/subdiagnostic-derive.rs:288:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:294:1 + --> $DIR/subdiagnostic-derive.rs:304:1 | -LL | / union AB { +LL | / union AC { LL | | LL | | span: u32, LL | | b: u64 @@ -167,95 +175,91 @@ LL | | } | |_^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:304:9 + --> $DIR/subdiagnostic-derive.rs:314:1 | -LL | #[label(slug = "label-ac-2")] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:301:9 + --> $DIR/subdiagnostic-derive.rs:311:1 | -LL | #[label(slug = "label-ac-1")] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:304:1 + --> $DIR/subdiagnostic-derive.rs:314:1 | -LL | #[label(slug = "label-ac-2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:301:1 + --> $DIR/subdiagnostic-derive.rs:311:1 | -LL | #[label(slug = "label-ac-1")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:313:30 +error: `#[label(parser::add_paren)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:323:28 | -LL | #[label(slug = "label-ad-1", slug = "label-ad-2")] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren, parser::add_paren)] + | ^^^^^^^^^^^^^^^^^ | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:313:9 - | -LL | #[label(slug = "label-ad-1", slug = "label-ad-2")] - | ^^^^^^^^^^^^^^^^^^^ + = help: a diagnostic slug must be the first argument to the attribute error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:327:5 + --> $DIR/subdiagnostic-derive.rs:336:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:324:5 + --> $DIR/subdiagnostic-derive.rs:333:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:333:8 + --> $DIR/subdiagnostic-derive.rs:342:8 | -LL | struct AF { +LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:370:42 + --> $DIR/subdiagnostic-derive.rs:379:47 | -LL | #[suggestion(slug = "...", code = "...", code = "...")] - | ^^^^^^^^^^^^ +LL | #[suggestion(parser::add_paren, code = "...", code = "...")] + | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:370:28 + --> $DIR/subdiagnostic-derive.rs:379:33 | -LL | #[suggestion(slug = "...", code = "...", code = "...")] - | ^^^^^^^^^^^^ +LL | #[suggestion(parser::add_paren, code = "...", code = "...")] + | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:388:5 + --> $DIR/subdiagnostic-derive.rs:397:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:385:5 + --> $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:399:5 + --> $DIR/subdiagnostic-derive.rs:408:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:394:1 + --> $DIR/subdiagnostic-derive.rs:403:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | -LL | | struct AK { +LL | | struct AL { LL | | #[primary_span] ... | LL | | applicability: Span, @@ -263,22 +267,22 @@ LL | | } | |_^ error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:405:1 + --> $DIR/subdiagnostic-derive.rs:414:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | -LL | | struct AL { +LL | | struct AM { LL | | #[primary_span] LL | | span: Span, LL | | } | |_^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:413:1 + --> $DIR/subdiagnostic-derive.rs:422:1 | -LL | / #[suggestion(slug = "...")] +LL | / #[suggestion(parser::add_paren)] LL | | -LL | | struct AM { +LL | | struct AN { LL | | #[primary_span] ... | LL | | applicability: Applicability, @@ -286,50 +290,50 @@ LL | | } | |_^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:423:41 + --> $DIR/subdiagnostic-derive.rs:432:46 | -LL | #[suggestion(slug = "...", code ="...", applicability = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:441:1 + --> $DIR/subdiagnostic-derive.rs:450:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | LL | | -LL | | struct AQ { +LL | | struct AR { LL | | var: String, LL | | } | |_^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:441:1 + --> $DIR/subdiagnostic-derive.rs:450:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | LL | | -LL | | struct AQ { +LL | | struct AR { LL | | var: String, LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:456:1 + --> $DIR/subdiagnostic-derive.rs:465:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:476:34 + --> $DIR/subdiagnostic-derive.rs:485:39 | -LL | #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] - | ^^^^^^^ +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:495:38 + --> $DIR/subdiagnostic-derive.rs:504:43 | -LL | #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] - | ^^^^^^^ +LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] + | ^^^^^^^ error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 @@ -338,52 +342,59 @@ LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:145:3 + --> $DIR/subdiagnostic-derive.rs:155:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:159:7 + --> $DIR/subdiagnostic-derive.rs:169:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:171:7 + --> $DIR/subdiagnostic-derive.rs:181:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:183:7 + --> $DIR/subdiagnostic-derive.rs:193:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:195:7 + --> $DIR/subdiagnostic-derive.rs:205:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:256:7 + --> $DIR/subdiagnostic-derive.rs:266:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:267:7 + --> $DIR/subdiagnostic-derive.rs:277:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:278:7 + --> $DIR/subdiagnostic-derive.rs:288:7 | LL | #[bar("...")] | ^^^ -error: aborting due to 51 previous errors +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`. -- cgit 1.4.1-3-g733a5