diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 99f856684abd..a5b8c0ebe25e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -1,5 +1,5 @@ use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; -use rustc_errors::msg; +use rustc_errors::{Diagnostic, msg}; use rustc_feature::template; use rustc_hir::Target; use rustc_hir::attrs::{ @@ -171,12 +171,15 @@ fn parse_single_test_doc_attr_item( if let Some(used_span) = self.attribute.no_crate_inject { let unused_span = path.span(); - cx.emit_lint( + cx.emit_dyn_lint( rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, - AttributeLintKind::UnusedDuplicate { - this: unused_span, - other: used_span, - warning: true, + move |dcx, level| { + rustc_errors::lints::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: true, + } + .into_diag(dcx, level) }, unused_span, ); diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index ec2b90331d80..aa9284e54d36 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -7,7 +7,8 @@ use private::Sealed; use rustc_ast::{AttrStyle, MetaItemLit, NodeId}; -use rustc_errors::{Diag, Diagnostic, Level, MultiSpan}; +use rustc_data_structures::sync::{DynSend, DynSync}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; use rustc_feature::{AttrSuggestionStyle, AttributeTemplate}; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::AttributeLintKind; @@ -461,11 +462,34 @@ pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuarant /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing /// must be delayed until after HIR is built. This method will take care of the details of /// that. - pub(crate) fn emit_lint>( + pub(crate) fn emit_lint( &mut self, lint: &'static Lint, kind: AttributeLintKind, - span: M, + span: impl Into, + ) { + self.emit_lint_inner(lint, EmitAttribute::Static(kind), span); + } + + /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing + /// must be delayed until after HIR is built. This method will take care of the details of + /// that. + pub(crate) fn emit_dyn_lint< + F: for<'a> Fn(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + DynSync + 'static, + >( + &mut self, + lint: &'static Lint, + callback: F, + span: impl Into, + ) { + self.emit_lint_inner(lint, EmitAttribute::Dynamic(Box::new(callback)), span); + } + + fn emit_lint_inner( + &mut self, + lint: &'static Lint, + kind: EmitAttribute, + span: impl Into, ) { if !matches!( self.stage.should_emit(), @@ -473,16 +497,19 @@ pub(crate) fn emit_lint>( ) { return; } - (self.emit_lint)(LintId::of(lint), span.into(), EmitAttribute::Static(kind)); + (self.emit_lint)(LintId::of(lint), span.into(), kind); } pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) { - self.emit_lint( + self.emit_dyn_lint( rustc_session::lint::builtin::UNUSED_ATTRIBUTES, - AttributeLintKind::UnusedDuplicate { - this: unused_span, - other: used_span, - warning: false, + move |dcx, level| { + rustc_errors::lints::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: false, + } + .into_diag(dcx, level) }, unused_span, ) @@ -493,12 +520,15 @@ pub(crate) fn warn_unused_duplicate_future_error( used_span: Span, unused_span: Span, ) { - self.emit_lint( + self.emit_dyn_lint( rustc_session::lint::builtin::UNUSED_ATTRIBUTES, - AttributeLintKind::UnusedDuplicate { - this: unused_span, - other: used_span, - warning: true, + move |dcx, level| { + rustc_errors::lints::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: true, + } + .into_diag(dcx, level) }, unused_span, ) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8651f58e0cfa..f4874652f6ac 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -77,6 +77,7 @@ pub mod emitter; pub mod formatting; pub mod json; +pub mod lints; mod lock; pub mod markdown; pub mod timings; diff --git a/compiler/rustc_errors/src/lints.rs b/compiler/rustc_errors/src/lints.rs new file mode 100644 index 000000000000..9c93a09bf764 --- /dev/null +++ b/compiler/rustc_errors/src/lints.rs @@ -0,0 +1,15 @@ +use rustc_macros::Diagnostic; +use rustc_span::Span; + +#[derive(Diagnostic)] +#[diag("unused attribute")] +pub struct UnusedDuplicate { + #[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, +} diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index fe4ed144b82f..7340ba0b2f39 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -35,9 +35,6 @@ pub struct DecorateAttrLint<'a, 'sess, 'tcx> { impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { match self.diagnostic { - &AttributeLintKind::UnusedDuplicate { this, other, warning } => { - lints::UnusedDuplicate { this, other, warning }.into_diag(dcx, level) - } AttributeLintKind::IllFormedAttributeInput { suggestions, docs, help } => { lints::IllFormedAttributeInput { num_suggestions: suggestions.len(), diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 67ca30bfb3cb..20d88505f042 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3365,19 +3365,6 @@ pub(crate) struct InvalidAttrStyle { pub target: &'static str, } -#[derive(Diagnostic)] -#[diag("unused attribute")] -pub(crate) struct UnusedDuplicate { - #[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, -} - #[derive(Diagnostic)] #[diag("malformed `doc` attribute input")] #[warning( diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 19477ca63315..ea5006c7f03f 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -654,11 +654,6 @@ pub enum DeprecatedSinceKind { #[derive(Debug)] pub enum AttributeLintKind { - UnusedDuplicate { - this: Span, - other: Span, - warning: bool, - }, IllFormedAttributeInput { suggestions: Vec, docs: Option<&'static str>,