diff --git a/compiler/rustc_errors/src/decorate_diag.rs b/compiler/rustc_errors/src/decorate_diag.rs index 7e53b8195d5b..a11082e29663 100644 --- a/compiler/rustc_errors/src/decorate_diag.rs +++ b/compiler/rustc_errors/src/decorate_diag.rs @@ -7,7 +7,7 @@ use crate::{Diag, DiagCtxtHandle, Diagnostic, Level}; -/// We can't implement `LintDiagnostic` for `BuiltinLintDiag`, because decorating some of its +/// We can't implement `Diagnostic` for `BuiltinLintDiag`, because decorating some of its /// variants requires types we don't have yet. So, handle that case separately. pub enum DecorateDiagCompat { Dynamic(Box FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static>), diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 888009bf9d4c..f68e6000ddf9 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -138,14 +138,6 @@ pub trait Subdiagnostic fn add_to_diag(self, diag: &mut Diag<'_, G>); } -/// Trait implemented by lint types. This should not be implemented manually. Instead, use -/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. -#[rustc_diagnostic_item = "LintDiagnostic"] -pub trait LintDiagnostic<'a, G: EmissionGuarantee> { - /// Decorate a lint with the information from this type. - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>); -} - #[derive(Clone, Debug, Encodable, Decodable)] pub(crate) struct DiagLocation { file: Cow<'static, str>, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 6c68dfccf86a..436149ee9dab 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -38,7 +38,7 @@ pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; pub use diagnostic::{ BugAbort, Diag, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee, FatalAbort, - LintDiagnostic, StringPart, Subdiag, Subdiagnostic, + StringPart, Subdiag, Subdiagnostic, }; pub use diagnostic_impls::{ DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index dc8231e5f0b0..2f7c3cc6a46d 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -4,7 +4,7 @@ use quote::quote; use synstructure::Structure; -use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind; +use crate::diagnostics::diagnostic_builder::each_variant; use crate::diagnostics::error::DiagnosticDeriveError; /// The central struct for constructing the `into_diag` method from an annotated struct. @@ -19,8 +19,7 @@ pub(crate) fn new(structure: Structure<'a>) -> Self { pub(crate) fn into_tokens(self) -> TokenStream { let DiagnosticDerive { mut structure } = self; - let kind = DiagnosticDeriveKind::Diagnostic; - let implementation = kind.each_variant(&mut structure, |mut builder, variant| { + let implementation = each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); @@ -64,52 +63,3 @@ fn into_diag( }) } } - -/// The central struct for constructing the `decorate_lint` method from an annotated struct. -pub(crate) struct LintDiagnosticDerive<'a> { - structure: Structure<'a>, -} - -impl<'a> LintDiagnosticDerive<'a> { - pub(crate) fn new(structure: Structure<'a>) -> Self { - Self { structure } - } - - pub(crate) fn into_tokens(self) -> TokenStream { - let LintDiagnosticDerive { mut structure } = self; - let kind = DiagnosticDeriveKind::LintDiagnostic; - let implementation = kind.each_variant(&mut structure, |mut builder, variant| { - let preamble = builder.preamble(variant); - let body = builder.body(variant); - - let Some(message) = builder.primary_message() else { - return DiagnosticDeriveError::ErrorHandled.to_compile_error(); - }; - let message = message.diag_message(Some(variant)); - let primary_message = quote! { - diag.primary_message(#message); - }; - - let formatting_init = &builder.formatting_init; - quote! { - #primary_message - #preamble - #formatting_init - #body - diag - } - }); - - structure.gen_impl(quote! { - gen impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for @Self { - #[track_caller] - fn decorate_lint<'__b>( - self, - diag: &'__b mut rustc_errors::Diag<'__a, ()> - ) { - #implementation; - } - } - }) - } -} diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index de8ee42caf45..e335037f2c4c 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -18,20 +18,54 @@ should_generate_arg, type_is_bool, type_is_unit, type_matches_path, }; -/// What kind of diagnostic is being derived - a fatal/error/warning or a lint? -#[derive(Clone, Copy, PartialEq, Eq)] -pub(crate) enum DiagnosticDeriveKind { - Diagnostic, - LintDiagnostic, +pub(crate) fn each_variant<'s, F>(structure: &mut Structure<'s>, f: F) -> TokenStream +where + F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream, +{ + let ast = structure.ast(); + let span = ast.span().unwrap(); + match ast.data { + syn::Data::Struct(..) | syn::Data::Enum(..) => (), + syn::Data::Union(..) => { + span_err(span, "diagnostic derives can only be used on structs and enums").emit(); + } + } + + if matches!(ast.data, syn::Data::Enum(..)) { + for attr in &ast.attrs { + span_err(attr.span().unwrap(), "unsupported type attribute for diagnostic derive enum") + .emit(); + } + } + + structure.bind_with(|_| synstructure::BindStyle::Move); + let variants = structure.each_variant(|variant| { + let span = match structure.ast().data { + syn::Data::Struct(..) => span, + // There isn't a good way to get the span of the variant, so the variant's + // name will need to do. + _ => variant.ast().ident.span().unwrap(), + }; + let builder = DiagnosticDeriveVariantBuilder { + span, + field_map: build_field_mapping(variant), + formatting_init: TokenStream::new(), + message: None, + code: None, + }; + f(builder, variant) + }); + + quote! { + match self { + #variants + } + } } /// Tracks persistent information required for a specific variant when building up individual calls -/// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for -/// fatal/errors/warnings and `LintDiagnostic` for lints. +/// to diagnostic methods for generated diagnostic derives. pub(crate) struct DiagnosticDeriveVariantBuilder { - /// The kind for the entire type. - pub kind: DiagnosticDeriveKind, - /// Initialization of format strings for code suggestions. pub formatting_init: TokenStream, @@ -51,60 +85,6 @@ pub(crate) struct DiagnosticDeriveVariantBuilder { pub code: SpannedOption<()>, } -impl DiagnosticDeriveKind { - /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the - /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions - /// or attributes on the type itself when input is an enum. - pub(crate) fn each_variant<'s, F>(self, structure: &mut Structure<'s>, f: F) -> TokenStream - where - F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream, - { - let ast = structure.ast(); - let span = ast.span().unwrap(); - match ast.data { - syn::Data::Struct(..) | syn::Data::Enum(..) => (), - syn::Data::Union(..) => { - span_err(span, "diagnostic derives can only be used on structs and enums").emit(); - } - } - - if matches!(ast.data, syn::Data::Enum(..)) { - for attr in &ast.attrs { - span_err( - attr.span().unwrap(), - "unsupported type attribute for diagnostic derive enum", - ) - .emit(); - } - } - - structure.bind_with(|_| synstructure::BindStyle::Move); - let variants = structure.each_variant(|variant| { - let span = match structure.ast().data { - syn::Data::Struct(..) => span, - // There isn't a good way to get the span of the variant, so the variant's - // name will need to do. - _ => variant.ast().ident.span().unwrap(), - }; - let builder = DiagnosticDeriveVariantBuilder { - kind: self, - span, - field_map: build_field_mapping(variant), - formatting_init: TokenStream::new(), - message: None, - code: None, - }; - f(builder, variant) - }); - - quote! { - match self { - #variants - } - } - } -} - impl DiagnosticDeriveVariantBuilder { pub(crate) fn primary_message(&self) -> Option<&Message> { match self.message.as_ref() { @@ -358,20 +338,11 @@ fn generate_inner_field_code( // `arg` call will not be generated. (Meta::Path(_), "skip_arg") => return Ok(quote! {}), (Meta::Path(_), "primary_span") => { - match self.kind { - DiagnosticDeriveKind::Diagnostic => { - report_error_if_not_applied_to_span(attr, &info)?; + report_error_if_not_applied_to_span(attr, &info)?; - return Ok(quote! { - diag.span(#binding); - }); - } - DiagnosticDeriveKind::LintDiagnostic => { - throw_invalid_attr!(attr, |diag| { - diag.help("the `primary_span` field attribute is not valid for lint diagnostics") - }) - } - } + return Ok(quote! { + diag.span(#binding); + }); } (Meta::Path(_), "subdiagnostic") => { return Ok(quote! { diag.subdiagnostic(#binding); }); diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index c0512e86bbcb..a5828cd715a8 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -6,7 +6,7 @@ mod subdiagnostic; mod utils; -use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; +use diagnostic::DiagnosticDerive; pub(super) use msg_macro::msg_macro; use proc_macro2::TokenStream; use subdiagnostic::SubdiagnosticDerive; @@ -51,38 +51,6 @@ pub(super) fn diagnostic_derive(s: Structure<'_>) -> TokenStream { DiagnosticDerive::new(s).into_tokens() } -/// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct, -/// independent from the actual lint emitting code. -/// -/// ```ignore (rust) -/// #[derive(LintDiagnostic)] -/// #[diag("unused attribute")] -/// pub(crate) struct UnusedAttribute { -/// #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] -/// pub this: Span, -/// #[note("attribute also specified here")] -/// pub other: Span, -/// #[warning( -/// "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" -/// )] -/// pub warning: bool, -/// } -/// ``` -/// -/// Then, later, to emit the error: -/// -/// ```ignore (rust) -/// cx.emit_span_lint(UNUSED_ATTRIBUTES, span, UnusedAttribute { -/// ... -/// }); -/// ``` -/// -/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: -/// -pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { - LintDiagnosticDerive::new(s).into_tokens() -} - /// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and /// suggestions to be specified as a structs or enums, independent from the actual diagnostics /// emitting code or diagnostic derives. @@ -99,7 +67,7 @@ pub(super) fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// Then, later, use the subdiagnostic in a diagnostic: /// /// ```ignore (rust) -/// #[derive(LintDiagnostic)] +/// #[derive(Diagnostic)] /// #[diag("unused doc comment")] /// pub(crate) struct BuiltinUnusedDocComment<'a> { /// pub kind: &'a str, diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index d7f75e08bac8..44969908b3f4 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -196,25 +196,6 @@ pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream { suggestion_hidden, suggestion_verbose)] => diagnostics::diagnostic_derive ); -decl_derive!( - [LintDiagnostic, attributes( - // struct attributes - diag, - help, - help_once, - note, - note_once, - warning, - // field attributes - skip_arg, - primary_span, - label, - subdiagnostic, - suggestion, - suggestion_short, - suggestion_hidden, - suggestion_verbose)] => diagnostics::lint_diagnostic_derive -); decl_derive!( [Subdiagnostic, attributes( // struct/variant attributes diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 7347fe6d9d5e..223b47c9044b 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -492,8 +492,8 @@ fn lint_level_impl( /// - [`TyCtxt::node_lint`] /// - `LintContext::opt_span_lint` /// -/// This function will replace `lint_level` once all `LintDiagnostic` items have been migrated to -/// `Diagnostic`. +/// This function will replace `lint_level` once all its callers have been replaced +/// with `diag_lint_level`. #[track_caller] pub fn diag_lint_level<'a, D: Diagnostic<'a, ()> + 'a>( sess: &'a Session, diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index ff6baabbb29a..628d35814684 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -4,7 +4,7 @@ use std::num::NonZero; use rustc_ast::NodeId; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, LintDiagnostic, msg}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, LintBuffer, msg}; use rustc_feature::GateIssue; use rustc_hir::attrs::{DeprecatedSince, Deprecation}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -131,15 +131,8 @@ fn into_diag( dcx: rustc_errors::DiagCtxtHandle<'a>, level: rustc_errors::Level, ) -> Diag<'a, G> { - let mut diag = Diag::new(dcx, level, ""); - self.decorate_lint(&mut diag); - diag - } -} - -impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for Deprecated { - fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { - diag.primary_message(match &self.since_kind { + let Self { sub, kind, path, note, since_kind } = self; + let mut diag = Diag::new(dcx, level, match &since_kind { DeprecatedSinceKind::InEffect => msg!( "use of deprecated {$kind} `{$path}`{$has_note -> [true] : {$note} @@ -160,21 +153,22 @@ fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { }" ) } - }); - diag.arg("kind", self.kind); - diag.arg("path", self.path); - if let DeprecatedSinceKind::InVersion(version) = self.since_kind { + }) + .with_arg("kind", kind) + .with_arg("path", path); + if let DeprecatedSinceKind::InVersion(version) = since_kind { diag.arg("version", version); } - if let Some(note) = self.note { + if let Some(note) = note { diag.arg("has_note", true); diag.arg("note", note); } else { diag.arg("has_note", false); } - if let Some(sub) = self.sub { + if let Some(sub) = sub { diag.subdiagnostic(sub); } + diag } } diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index b27e52f32bf2..514d1e2a9729 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; -use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -109,8 +109,7 @@ impl Subdiagnostic for GappedRange { fn add_to_diag(self, diag: &mut Diag<'_, G>) { let GappedRange { span, gap, first_range } = self; - // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` - // does not support `#[subdiagnostic(eager)]`... + // FIXME(mejrs) Use `#[subdiagnostic(eager)]` instead let message = format!( "this could appear to continue range `{first_range}`, but `{gap}` isn't matched by \ either of them" @@ -131,10 +130,12 @@ pub(crate) struct NonExhaustiveOmittedPattern<'tcx> { pub uncovered: Uncovered, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the lint level must be set on the whole match")] #[help("it no longer has any effect to set the lint level on an individual match arm")] pub(crate) struct NonExhaustiveOmittedPatternLintOnArm { + #[primary_span] + pub span: Span, #[label("remove this attribute")] pub lint_span: Span, #[suggestion( diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 3da744dc8c02..5a8adf4841c4 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -92,17 +92,13 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( let LevelAndSource { level, src, .. } = rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, arm.arm_data); if !matches!(level, rustc_session::lint::Level::Allow) { - let decorator = NonExhaustiveOmittedPatternLintOnArm { + rcx.tcx.dcx().emit_warn(NonExhaustiveOmittedPatternLintOnArm { + span: arm.pat.data().span, lint_span: src.span(), suggest_lint_on_match: rcx.whole_match_span.map(|span| span.shrink_to_lo()), lint_level: level.as_str(), lint_name: "non_exhaustive_omitted_patterns", - }; - - use rustc_errors::LintDiagnostic; - let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().span, ""); - decorator.decorate_lint(&mut err); - err.emit(); + }); } } } diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index a99f6a2849c3..a3a7a11258c8 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -1,6 +1,6 @@ # Diagnostic and subdiagnostic structs -rustc has three diagnostic traits that can be used to create diagnostics: -`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. +rustc has two diagnostic traits that can be used to create diagnostics: +`Diagnostic` and `Subdiagnostic`. For simple diagnostics, derived impls can be used, e.g. `#[derive(Diagnostic)]`. They are only suitable for simple diagnostics that @@ -8,12 +8,12 @@ don't require much logic in deciding whether or not to add additional subdiagnos In cases where diagnostics require more complex or dynamic behavior, such as conditionally adding subdiagnostics, customizing the rendering logic, or selecting messages at runtime, you will need to manually implement -the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`). +the corresponding trait (`Diagnostic` or `Subdiagnostic`). This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures. Diagnostic can be translated into different languages. -## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` +## `#[derive(Diagnostic)]` Consider the [definition][defn] of the "field already declared" diagnostic shown below: @@ -123,8 +123,8 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { }); ``` -### Reference for `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` -`#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the following attributes: +### Reference for `#[derive(Diagnostic)]` +`#[derive(Diagnostic)]` supports the following attributes: - `#[diag("message", code = "...")]` - _Applied to struct or enum variant._ @@ -171,7 +171,6 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { - Adds the subdiagnostic represented by the subdiagnostic struct. - `#[primary_span]` (_Optional_) - _Applied to `Span` fields on `Subdiagnostic`s. - Not used for `LintDiagnostic`s._ - Indicates the primary span of the diagnostic. - `#[skip_arg]` (_Optional_) - _Applied to any field._ diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index 88526ec1c5c7..cf95727e2a67 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -32,7 +32,7 @@ There are two ways of writing translatable diagnostics: deciding to emit subdiagnostics and can therefore be represented as diagnostic structs). See [the diagnostic and subdiagnostic structs documentation](./diagnostic-structs.md). 2. Using typed identifiers with `Diag` APIs (in - `Diagnostic` or `Subdiagnostic` or `LintDiagnostic` implementations). + `Diagnostic` or `Subdiagnostic` implementations). When adding or changing a translatable diagnostic, you don't need to worry about the translations. diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs index 759a9412f769..26d92126fe87 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -20,7 +20,7 @@ use rustc_span::Span; extern crate rustc_macros; -use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, Subdiagnostic}; extern crate rustc_middle; use rustc_middle::ty::Ty; @@ -495,18 +495,6 @@ struct LabelWithTrailingList { span: Span, } -#[derive(LintDiagnostic)] -#[diag("this is an example message")] -struct LintsGood {} - -#[derive(LintDiagnostic)] -#[diag("this is an example message")] -struct PrimarySpanOnLint { - #[primary_span] - //~^ ERROR `#[primary_span]` is not a valid attribute - span: Span, -} - #[derive(Diagnostic)] #[diag("this is an example message", code = E0123)] struct ErrorWithMultiSpan { @@ -542,13 +530,6 @@ struct WarnAttribute {} //~| ERROR cannot find attribute `lint` in this scope struct LintAttributeOnSessionDiag {} -#[derive(LintDiagnostic)] -#[lint("this is an example message", code = E0123)] -//~^ ERROR `#[lint(...)]` is not a valid attribute -//~| ERROR diagnostic message not specified -//~| ERROR cannot find attribute `lint` in this scope -struct LintAttributeOnLintDiag {} - #[derive(Diagnostic)] #[diag("this is an example message", code = E0123)] struct DuplicatedSuggestionCode { @@ -670,14 +651,6 @@ struct SubdiagnosticBadLitStr { note: Note, } -#[derive(LintDiagnostic)] -#[diag("this is an example message")] -struct SubdiagnosticEagerLint { - #[subdiagnostic(eager)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute - note: Note, -} - #[derive(Diagnostic)] #[diag("this is an example message")] struct SubdiagnosticEagerFormerlyCorrect { diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr index b32235c02b07..48138fc9fb55 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr @@ -300,22 +300,14 @@ error: derive(Diagnostic): no nested attribute expected here LL | #[label("with a label", foo("..."))] | ^^^ -error: derive(Diagnostic): `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:505:5 - | -LL | #[primary_span] - | ^ - | - = help: the `primary_span` field attribute is not valid for lint diagnostics - error: derive(Diagnostic): `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:525:1 + --> $DIR/diagnostic-derive-inline.rs:513:1 | LL | #[error("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:525:1 + --> $DIR/diagnostic-derive-inline.rs:513:1 | LL | #[error("this is an example message", code = E0123)] | ^ @@ -323,13 +315,13 @@ LL | #[error("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:532:1 + --> $DIR/diagnostic-derive-inline.rs:520:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:532:1 + --> $DIR/diagnostic-derive-inline.rs:520:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ @@ -337,27 +329,13 @@ LL | #[warn_("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:539:1 + --> $DIR/diagnostic-derive-inline.rs:527:1 | LL | #[lint("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:539:1 - | -LL | #[lint("this is an example message", code = E0123)] - | ^ - | - = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` - -error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:546:1 - | -LL | #[lint("this is an example message", code = E0123)] - | ^ - -error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:546:1 + --> $DIR/diagnostic-derive-inline.rs:527:1 | LL | #[lint("this is an example message", code = E0123)] | ^ @@ -365,19 +343,19 @@ LL | #[lint("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:555:53 + --> $DIR/diagnostic-derive-inline.rs:536:53 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:555:39 + --> $DIR/diagnostic-derive-inline.rs:536:39 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:564:24 + --> $DIR/diagnostic-derive-inline.rs:545:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -385,7 +363,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:572:17 + --> $DIR/diagnostic-derive-inline.rs:553:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -393,13 +371,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:579:5 + --> $DIR/diagnostic-derive-inline.rs:560:5 | LL | #[suggestion("with a suggestion")] | ^ error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:586:1 + --> $DIR/diagnostic-derive-inline.rs:567:1 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -407,7 +385,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:589:1 + --> $DIR/diagnostic-derive-inline.rs:570:1 | LL | #[multipart_suggestion()] | ^ @@ -415,7 +393,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:593:5 + --> $DIR/diagnostic-derive-inline.rs:574:5 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -423,7 +401,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:601:1 + --> $DIR/diagnostic-derive-inline.rs:582:1 | LL | #[suggestion("with a suggestion", code = "...")] | ^ @@ -431,7 +409,7 @@ LL | #[suggestion("with a suggestion", code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:610:1 + --> $DIR/diagnostic-derive-inline.rs:591:1 | LL | #[label] | ^ @@ -439,73 +417,67 @@ LL | #[label] = help: subdiagnostic message is missing error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:644:5 + --> $DIR/diagnostic-derive-inline.rs:625:5 | LL | #[subdiagnostic(bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:652:5 + --> $DIR/diagnostic-derive-inline.rs:633:5 | LL | #[subdiagnostic = "bad"] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:660:5 + --> $DIR/diagnostic-derive-inline.rs:641:5 | LL | #[subdiagnostic(bad, bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:668:5 + --> $DIR/diagnostic-derive-inline.rs:649:5 | LL | #[subdiagnostic("bad")] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:676:5 + --> $DIR/diagnostic-derive-inline.rs:657:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:684:5 - | -LL | #[subdiagnostic(eager)] - | ^ - -error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:705:5 + --> $DIR/diagnostic-derive-inline.rs:678:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive-inline.rs:736:44 + --> $DIR/diagnostic-derive-inline.rs:709:44 | LL | #[suggestion("with a suggestion", code())] | ^ error: derive(Diagnostic): `code(...)` must contain only string literals - --> $DIR/diagnostic-derive-inline.rs:744:44 + --> $DIR/diagnostic-derive-inline.rs:717:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: unexpected token, expected `)` - --> $DIR/diagnostic-derive-inline.rs:744:44 + --> $DIR/diagnostic-derive-inline.rs:717:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: expected string literal - --> $DIR/diagnostic-derive-inline.rs:753:46 + --> $DIR/diagnostic-derive-inline.rs:726:46 | LL | #[suggestion("with a suggestion", code = 3)] | ^ error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:768:5 + --> $DIR/diagnostic-derive-inline.rs:741:5 | LL | #[suggestion("with a suggestion", code = "")] | ^ @@ -515,7 +487,7 @@ LL | #[suggestion("with a suggestion", code = "")] = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` error: derive(Diagnostic): Variable `nosub` not found in diagnostic - --> $DIR/diagnostic-derive-inline.rs:780:8 + --> $DIR/diagnostic-derive-inline.rs:753:8 | LL | #[diag("does not exist: {$nosub}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -535,7 +507,7 @@ LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive-inline.rs:525:3 + --> $DIR/diagnostic-derive-inline.rs:513:3 | LL | #[error("this is an example message", code = E0123)] | ^^^^^ @@ -547,7 +519,7 @@ LL | struct ErrorAttribute {} | error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive-inline.rs:532:3 + --> $DIR/diagnostic-derive-inline.rs:520:3 | LL | #[warn_("this is an example message", code = E0123)] | ^^^^^ @@ -559,19 +531,7 @@ LL + #[warn("this is an example message", code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:539:3 - | -LL | #[lint("this is an example message", code = E0123)] - | ^^^^ - | -help: a built-in attribute with a similar name exists - | -LL - #[lint("this is an example message", code = E0123)] -LL + #[link("this is an example message", code = E0123)] - | - -error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:546:3 + --> $DIR/diagnostic-derive-inline.rs:527:3 | LL | #[lint("this is an example message", code = E0123)] | ^^^^ @@ -583,7 +543,7 @@ LL + #[link("this is an example message", code = E0123)] | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:586:3 + --> $DIR/diagnostic-derive-inline.rs:567:3 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -595,7 +555,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:589:3 + --> $DIR/diagnostic-derive-inline.rs:570:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ @@ -607,7 +567,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:593:7 + --> $DIR/diagnostic-derive-inline.rs:574:7 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -636,6 +596,6 @@ note: required by a bound in `Diag::<'a, G>::arg` = note: in this macro invocation = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 81 previous errors +error: aborting due to 76 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lint/decorate-ice/decorate-def-path-str-ice.rs b/tests/ui/lint/decorate-ice/decorate-def-path-str-ice.rs index 8116e36ed0d9..3bb9882d348a 100644 --- a/tests/ui/lint/decorate-ice/decorate-def-path-str-ice.rs +++ b/tests/ui/lint/decorate-ice/decorate-def-path-str-ice.rs @@ -3,17 +3,16 @@ // Previously, this test ICEs when the `unused_must_use` lint is suppressed via the combination of // `-A warnings` and `--cap-lints=warn`, because: // -// - Its lint diagnostic struct `UnusedDef` implements `LintDiagnostic` manually and in the impl +// - Its lint diagnostic struct `UnusedDef` implements `Diagnostic` manually and in the impl // `def_path_str` was called (which calls `trimmed_def_path`, which will produce a // `must_produce_diag` ICE if a trimmed def path is constructed but never emitted in a diagnostic // because it is expensive to compute). -// - A `LintDiagnostic` has a `decorate_lint` method which decorates a `Diag` with lint-specific -// information. This method is wrapped by a `decorate` closure in `TyCtxt` diagnostic emission -// machinery, and the `decorate` closure called as late as possible. -// - `decorate`'s invocation is delayed as late as possible until `lint_level` is called. +// - A `Diagnostic` has an `into_diag` method which generates a `Diag` with (potentially) +// lint-specific information. +// - The `into_diag` method is called as late as possible until `diag_lint_level` is called. // - If a lint's corresponding diagnostic is suppressed (to be effectively allow at the final // emission time) via `-A warnings` or `--cap-lints=allow` (or `-A warnings` + `--cap-lints=warn` -// like in this test case), `decorate` is still called and a diagnostic is still constructed -- +// like in this test case), `into_diag` is still called and a diagnostic is still constructed -- // but the diagnostic is never eventually emitted, triggering the aforementioned // `must_produce_diag` ICE due to use of `trimmed_def_path`. //