diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 0702732c1f81..3566bd384f4a 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -36,31 +36,6 @@ pub struct DecorateBuiltinLint<'sess, 'tcx> { impl<'a> Diagnostic<'a, ()> for DecorateBuiltinLint<'_, '_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { match self.diagnostic { - BuiltinLintDiag::UnusedImports { - remove_whole_use, - num_to_remove, - remove_spans, - test_module_span, - span_snippets, - } => { - let sugg = if remove_whole_use { - lints::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] } - } else { - lints::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove } - }; - let test_module_span = - test_module_span.map(|span| self.sess.source_map().guess_head_span(span)); - - lints::UnusedImports { - sugg, - test_module_span, - num_snippets: span_snippets.len(), - span_snippets: DiagArgValue::StrListSepByAnd( - span_snippets.into_iter().map(Cow::Owned).collect(), - ), - } - .into_diag(dcx, level) - } BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, position_sp_for_msg, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 3eaa9ab260b1..0a24d2d0cdb9 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3039,50 +3039,6 @@ pub(crate) struct IllFormedAttributeInputHelp { pub lint: String, } -#[derive(Diagnostic)] -#[diag( - "{$num_snippets -> - [one] unused import: {$span_snippets} - *[other] unused imports: {$span_snippets} - }" -)] -pub(crate) struct UnusedImports { - #[subdiagnostic] - pub sugg: UnusedImportsSugg, - #[help("if this is a test module, consider adding a `#[cfg(test)]` to the containing module")] - pub test_module_span: Option, - - pub span_snippets: DiagArgValue, - pub num_snippets: usize, -} - -#[derive(Subdiagnostic)] -pub(crate) enum UnusedImportsSugg { - #[suggestion( - "remove the whole `use` item", - applicability = "machine-applicable", - code = "", - style = "tool-only" - )] - RemoveWholeUse { - #[primary_span] - span: Span, - }, - #[multipart_suggestion( - "{$num_to_remove -> - [one] remove the unused import - *[other] remove the unused imports - }", - applicability = "machine-applicable", - style = "tool-only" - )] - RemoveImports { - #[suggestion_part(code = "")] - remove_spans: Vec, - num_to_remove: usize, - }, -} - #[derive(Diagnostic)] #[diag("named argument `{$named_arg_name}` is not used by name")] pub(crate) struct NamedArgumentUsedPositionally { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 83816e1e7123..d235e66c20d8 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -656,13 +656,6 @@ pub enum DeprecatedSinceKind { // becomes hacky (and it gets allocated). #[derive(Debug)] pub enum BuiltinLintDiag { - UnusedImports { - remove_whole_use: bool, - num_to_remove: usize, - remove_spans: Vec, - test_module_span: Option, - span_snippets: Vec, - }, NamedArgumentUsedPositionally { /// Span where the named argument is used by position and will be replaced with the named /// argument name diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 8e150b7f3a5d..cdd809bdc173 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -23,13 +23,14 @@ // - `check_unused` finally emits the diagnostics based on the data generated // in the last step +use std::borrow::Cow; + use rustc_ast as ast; use rustc_ast::visit::{self, Visitor}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; -use rustc_errors::MultiSpan; +use rustc_errors::{DiagArgValue, Diagnostic, MultiSpan}; use rustc_hir::def::{DefKind, Res}; -use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS, UNUSED_QUALIFICATIONS, }; @@ -496,16 +497,32 @@ pub(crate) fn check_unused(&mut self, krate: &ast::Crate) { } }; - visitor.r.lint_buffer.buffer_lint( + visitor.r.lint_buffer.dyn_buffer_lint_any( UNUSED_IMPORTS, unused.use_tree_id, ms, - BuiltinLintDiag::UnusedImports { - remove_whole_use, - num_to_remove, - remove_spans, - test_module_span, - span_snippets, + move |dcx, level, sess| { + let sugg = if remove_whole_use { + errors::UnusedImportsSugg::RemoveWholeUse { span: remove_spans[0] } + } else { + errors::UnusedImportsSugg::RemoveImports { remove_spans, num_to_remove } + }; + let test_module_span = test_module_span.map(|span| { + sess.downcast_ref::() + .expect("expected a `Session`") + .source_map() + .guess_head_span(span) + }); + + errors::UnusedImports { + sugg, + test_module_span, + num_snippets: span_snippets.len(), + span_snippets: DiagArgValue::StrListSepByAnd( + span_snippets.into_iter().map(Cow::Owned).collect(), + ), + } + .into_diag(dcx, level) }, ); } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index d4f67b87261d..bcc754fd984d 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, Diagnostic, ElidedLifetimeInPathSubdiag, + Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -1747,3 +1747,47 @@ pub(crate) struct ElidedLifetimesInPaths { #[subdiagnostic] pub subdiag: rustc_errors::ElidedLifetimeInPathSubdiag, } + +#[derive(Diagnostic)] +#[diag( + "{$num_snippets -> + [one] unused import: {$span_snippets} + *[other] unused imports: {$span_snippets} + }" +)] +pub(crate) struct UnusedImports { + #[subdiagnostic] + pub sugg: UnusedImportsSugg, + #[help("if this is a test module, consider adding a `#[cfg(test)]` to the containing module")] + pub test_module_span: Option, + + pub span_snippets: DiagArgValue, + pub num_snippets: usize, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnusedImportsSugg { + #[suggestion( + "remove the whole `use` item", + applicability = "machine-applicable", + code = "", + style = "tool-only" + )] + RemoveWholeUse { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + "{$num_to_remove -> + [one] remove the unused import + *[other] remove the unused imports + }", + applicability = "machine-applicable", + style = "tool-only" + )] + RemoveImports { + #[suggestion_part(code = "")] + remove_spans: Vec, + num_to_remove: usize, + }, +}