From f64bdadd3f504022b9f11b7aa26402baa615d9fe Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 26 Feb 2026 16:56:45 +0100 Subject: [PATCH 1/6] Remove unused `LintContext::emit_lint` method --- compiler/rustc_lint/src/context.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 971170aaba304..2b26caaed8741 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -535,8 +535,8 @@ pub trait LintContext { decorate: impl for<'a> Diagnostic<'a, ()>, ); - /// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`, - /// typically generated by `#[derive(LintDiagnostic)]`). + /// Emit a lint at `span` from a lint struct (some type that implements `Diagnostic`, + /// typically generated by `#[derive(Diagnostic)]`). fn emit_span_lint>( &self, lint: &'static Lint, @@ -573,16 +573,8 @@ pub trait LintContext { self.opt_span_lint(lint, Some(span), decorate); } - /// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically - /// generated by `#[derive(LintDiagnostic)]`). - fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> LintDiagnostic<'a, ()>) { - self.opt_span_lint(lint, None as Option, |lint| { - decorator.decorate_lint(lint); - }); - } - - /// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically - /// generated by `#[derive(LintDiagnostic)]`). + /// Emit a lint from a lint struct (some type that implements `Diagnostic`, typically + /// generated by `#[derive(Diagnostic)]`). fn emit_diag_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a, ()>) { self.opt_span_diag_lint(lint, None as Option, decorator); } From a3cfcaa6eb63ad4695ab6698e736f92c04a7d0eb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 26 Feb 2026 17:46:32 +0100 Subject: [PATCH 2/6] Migrate most `rustc_lint` lint to `Diagnostic` --- compiler/rustc_lint/src/early.rs | 2 +- compiler/rustc_lint/src/early/diagnostics.rs | 213 +++++++++---------- compiler/rustc_lint/src/lints.rs | 122 +++++------ 3 files changed, 157 insertions(+), 180 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 0295df2feca56..1c205035934b5 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -36,7 +36,7 @@ impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; - self.context.opt_span_lint(lint_id.lint, span, |diag| match diagnostic { + self.context.opt_span_diag_lint(lint_id.lint, span, |diag| match diagnostic { DecorateDiagCompat::Builtin(b) => { diagnostics::decorate_builtin_lint(self.context.sess(), self.tcx, b, diag); } diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 5aee3f382ff3c..b5a5dce681d07 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -16,11 +16,11 @@ use crate::lints; mod check_cfg; -pub fn decorate_builtin_lint( +pub fn decorate_builtin_lint)>( sess: &Session, tcx: Option>, diagnostic: BuiltinLintDiag, - diag: &mut Diag<'_, ()>, + callback: F, ) { match diagnostic { BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { @@ -41,13 +41,12 @@ pub fn decorate_builtin_lint( spans: spans.iter().map(|(_c, span)| *span).collect(), }); - lints::UnicodeTextFlow { + callback(lints::UnicodeTextFlow { comment_span, characters, suggestions, num_codepoints: spans.len(), - } - .decorate_lint(diag); + }); } BuiltinLintDiag::AbsPathWithModule(mod_span) => { let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) { @@ -60,13 +59,12 @@ pub fn decorate_builtin_lint( } Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), }; - lints::AbsPathWithModule { + callback(lints::AbsPathWithModule { sugg: lints::AbsPathWithModuleSugg { span: mod_span, applicability, replacement }, - } - .decorate_lint(diag); + }); } BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - lints::ElidedLifetimesInPaths { + callback(lints::ElidedLifetimesInPaths { subdiag: elided_lifetime_in_path_suggestion( sess.source_map(), n, @@ -74,8 +72,7 @@ pub fn decorate_builtin_lint( incl_angl_brckt, insertion_span, ), - } - .decorate_lint(diag); + }); } BuiltinLintDiag::UnusedImports { remove_whole_use, @@ -92,15 +89,14 @@ pub fn decorate_builtin_lint( let test_module_span = test_module_span.map(|span| sess.source_map().guess_head_span(span)); - lints::UnusedImports { + callback(lints::UnusedImports { sugg, test_module_span, num_snippets: span_snippets.len(), span_snippets: DiagArgValue::StrListSepByAnd( span_snippets.into_iter().map(Cow::Owned).collect(), ), - } - .decorate_lint(diag); + }); } BuiltinLintDiag::RedundantImport(spans, ident) => { let subs = spans @@ -114,7 +110,7 @@ pub fn decorate_builtin_lint( })(span) }) .collect(); - lints::RedundantImport { subs, ident }.decorate_lint(diag); + callback(lints::RedundantImport { subs, ident }); } BuiltinLintDiag::DeprecatedMacro { suggestion, @@ -129,45 +125,46 @@ pub fn decorate_builtin_lint( suggestion, }); - stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind } - .decorate_lint(diag); + callback(stability::Deprecated { + sub, + kind: "macro".to_owned(), + path, + note, + since_kind, + }); } BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; - if is_foreign { + callback(if is_foreign { lints::PatternsInFnsWithoutBody::Foreign { sub } } else { lints::PatternsInFnsWithoutBody::Bodiless { sub } - } - .decorate_lint(diag); + }); } BuiltinLintDiag::ReservedPrefix(label_span, prefix) => { - lints::ReservedPrefix { + callback(lints::ReservedPrefix { label: label_span, suggestion: label_span.shrink_to_hi(), prefix, - } - .decorate_lint(diag); + }); } BuiltinLintDiag::RawPrefix(label_span) => { - lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } - .decorate_lint(diag); + callback(lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }); } BuiltinLintDiag::ReservedString { is_string, suggestion } => { if is_string { - lints::ReservedString { suggestion }.decorate_lint(diag); + callback(lints::ReservedString { suggestion }); } else { - lints::ReservedMultihash { suggestion }.decorate_lint(diag); + callback(lints::ReservedMultihash { suggestion }); } } BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => { - lints::BreakWithLabelAndLoop { + callback(lints::BreakWithLabelAndLoop { sub: lints::BreakWithLabelAndLoopSub { left: sugg_span.shrink_to_lo(), right: sugg_span.shrink_to_hi(), }, - } - .decorate_lint(diag); + }); } BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { let suggestion = match sugg { @@ -178,7 +175,7 @@ pub fn decorate_builtin_lint( }, None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }, }; - lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag); + callback(lints::DeprecatedWhereClauseLocation { suggestion }); } BuiltinLintDiag::SingleUseLifetime { param_span, @@ -205,11 +202,10 @@ pub fn decorate_builtin_lint( None }; - lints::SingleUseLifetime { suggestion, param_span, use_span, ident } - .decorate_lint(diag); + callback(lints::SingleUseLifetime { suggestion, param_span, use_span, ident }); } BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { - lints::UnusedLifetime { deletion_span, ident }.decorate_lint(diag); + callback(lints::UnusedLifetime { deletion_span, ident }); } BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, @@ -237,14 +233,13 @@ pub fn decorate_builtin_lint( (None, String::new()) }; - lints::NamedArgumentUsedPositionally { + callback(lints::NamedArgumentUsedPositionally { named_arg_sp, position_label_sp: position_sp_for_msg, suggestion, name, named_arg_name, - } - .decorate_lint(diag); + }); } BuiltinLintDiag::AmbiguousGlobReexports { name, @@ -252,13 +247,12 @@ pub fn decorate_builtin_lint( first_reexport_span, duplicate_reexport_span, } => { - lints::AmbiguousGlobReexports { + callback(lints::AmbiguousGlobReexports { first_reexport: first_reexport_span, duplicate_reexport: duplicate_reexport_span, name, namespace, - } - .decorate_lint(diag); + }); } BuiltinLintDiag::HiddenGlobReexports { name, @@ -266,17 +260,16 @@ pub fn decorate_builtin_lint( glob_reexport_span, private_item_span, } => { - lints::HiddenGlobReexports { + callback(lints::HiddenGlobReexports { glob_reexport: glob_reexport_span, private_item: private_item_span, name, namespace, - } - .decorate_lint(diag); + }); } BuiltinLintDiag::UnusedQualifications { removal_span } => { - lints::UnusedQualifications { removal_span }.decorate_lint(diag); + callback(lints::UnusedQualifications { removal_span }); } BuiltinLintDiag::AssociatedConstElidedLifetime { elided, @@ -285,63 +278,57 @@ pub fn decorate_builtin_lint( } => { let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; let code = if elided { "'static " } else { "'static" }; - lints::AssociatedConstElidedLifetime { + callback(lints::AssociatedConstElidedLifetime { span: lt_span, code, elided, lifetimes_in_scope, - } - .decorate_lint(diag); + }); } BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span { Some(wildcard_span) => { - lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span } - .decorate_lint(diag) + callback(lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }) } - None => lints::UnreachableCfgSelectPredicate { span }.decorate_lint(diag), + None => callback(lints::UnreachableCfgSelectPredicate { span }), }, BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { - lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) - } - BuiltinLintDiag::UnusedVisibility(span) => { - lints::UnusedVisibility { span }.decorate_lint(diag) + callback(lints::UnusedCrateDependency { extern_crate, local_crate }) } - BuiltinLintDiag::AttributeLint(kind) => decorate_attribute_lint(sess, tcx, &kind, diag), + BuiltinLintDiag::UnusedVisibility(span) => callback(lints::UnusedVisibility { span }), + BuiltinLintDiag::AttributeLint(kind) => decorate_attribute_lint(sess, tcx, &kind, callback), } } -pub fn decorate_attribute_lint( +pub fn decorate_attribute_lint)>( sess: &Session, tcx: Option>, kind: &AttributeLintKind, - diag: &mut Diag<'_, ()>, + callback: F, ) { match kind { &AttributeLintKind::UnusedDuplicate { this, other, warning } => { - lints::UnusedDuplicate { this, other, warning }.decorate_lint(diag) + callback(lints::UnusedDuplicate { this, other, warning }) } AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => { - lints::IllFormedAttributeInput { + callback(lints::IllFormedAttributeInput { num_suggestions: suggestions.len(), suggestions: DiagArgValue::StrListSepByAnd( suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), ), has_docs: docs.is_some(), docs: docs.unwrap_or(""), - } - .decorate_lint(diag) + }) } AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => { - lints::EmptyAttributeList { + callback(lints::EmptyAttributeList { attr_span: *first_span, attr_path: attr_path.clone(), valid_without_list: *valid_without_list, - } - .decorate_lint(diag) + }) } AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => { - lints::InvalidTargetLint { + callback(lints::InvalidTargetLint { name: name.clone(), target, applied: DiagArgValue::StrListSepByAnd( @@ -349,129 +336,119 @@ pub fn decorate_attribute_lint( ), only, attr_span: *attr_span, - } - .decorate_lint(diag) + }) } &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => { - lints::InvalidAttrStyle { + callback(lints::InvalidAttrStyle { name: name.clone(), is_used_as_inner, target_span: (!is_used_as_inner).then_some(target_span), target, - } - .decorate_lint(diag) + }) } &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => { - lints::UnsafeAttrOutsideUnsafeLint { + callback(lints::UnsafeAttrOutsideUnsafeLint { span: attribute_name_span, suggestion: sugg_spans .map(|(left, right)| lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }), - } - .decorate_lint(diag) + }) } &AttributeLintKind::UnexpectedCfgName(name, value) => { - check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag) + callback(check_cfg::unexpected_cfg_name(sess, tcx, name, value)) } &AttributeLintKind::UnexpectedCfgValue(name, value) => { - check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag) + callback(check_cfg::unexpected_cfg_value(sess, tcx, name, value)) } &AttributeLintKind::DuplicateDocAlias { first_definition } => { - lints::DocAliasDuplicated { first_defn: first_definition }.decorate_lint(diag) + callback(lints::DocAliasDuplicated { first_defn: first_definition }) } &AttributeLintKind::DocAutoCfgExpectsHideOrShow => { - lints::DocAutoCfgExpectsHideOrShow.decorate_lint(diag) + callback(lints::DocAutoCfgExpectsHideOrShow) } - &AttributeLintKind::AmbiguousDeriveHelpers => { - lints::AmbiguousDeriveHelpers.decorate_lint(diag) - } + &AttributeLintKind::AmbiguousDeriveHelpers => callback(lints::AmbiguousDeriveHelpers), &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => { - lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.decorate_lint(diag) + callback(lints::DocAutoCfgHideShowUnexpectedItem { attr_name }) } &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => { - lints::DocAutoCfgHideShowExpectsList { attr_name }.decorate_lint(diag) + callback(lints::DocAutoCfgHideShowExpectsList { attr_name }) } - &AttributeLintKind::DocInvalid => { lints::DocInvalid }.decorate_lint(diag), + &AttributeLintKind::DocInvalid => callback(lints::DocInvalid), &AttributeLintKind::DocUnknownInclude { span, inner, value } => { - lints::DocUnknownInclude { inner, value, sugg: (span, Applicability::MaybeIncorrect) } + callback(lints::DocUnknownInclude { + inner, + value, + sugg: (span, Applicability::MaybeIncorrect), + }) } - .decorate_lint(diag), &AttributeLintKind::DocUnknownSpotlight { span } => { - lints::DocUnknownSpotlight { sugg_span: span }.decorate_lint(diag) + callback(lints::DocUnknownSpotlight { sugg_span: span }) } &AttributeLintKind::DocUnknownPasses { name, span } => { - lints::DocUnknownPasses { name, note_span: span }.decorate_lint(diag) + callback(lints::DocUnknownPasses { name, note_span: span }) } &AttributeLintKind::DocUnknownPlugins { span } => { - lints::DocUnknownPlugins { label_span: span }.decorate_lint(diag) + callback(lints::DocUnknownPlugins { label_span: span }) } - &AttributeLintKind::DocUnknownAny { name } => { - lints::DocUnknownAny { name }.decorate_lint(diag) - } + &AttributeLintKind::DocUnknownAny { name } => callback(lints::DocUnknownAny { name }), - &AttributeLintKind::DocAutoCfgWrongLiteral => { - lints::DocAutoCfgWrongLiteral.decorate_lint(diag) - } + &AttributeLintKind::DocAutoCfgWrongLiteral => callback(lints::DocAutoCfgWrongLiteral), - &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.decorate_lint(diag), + &AttributeLintKind::DocTestTakesList => callback(lints::DocTestTakesList), - &AttributeLintKind::DocTestUnknown { name } => { - lints::DocTestUnknown { name }.decorate_lint(diag) - } + &AttributeLintKind::DocTestUnknown { name } => callback(lints::DocTestUnknown { name }), - &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.decorate_lint(diag), + &AttributeLintKind::DocTestLiteral => callback(lints::DocTestLiteral), - &AttributeLintKind::AttrCrateLevelOnly => lints::AttrCrateLevelOnly.decorate_lint(diag), + &AttributeLintKind::AttrCrateLevelOnly => callback(lints::AttrCrateLevelOnly), &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => { - lints::DoNotRecommendDoesNotExpectArgs.decorate_lint(diag) + callback(lints::DoNotRecommendDoesNotExpectArgs) } - &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes { - sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), + &AttributeLintKind::CrateTypeUnknown { span, suggested } => { + callback(lints::UnknownCrateTypes { + sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), + }) } - .decorate_lint(diag), - &AttributeLintKind::MalformedDoc => lints::MalformedDoc.decorate_lint(diag), + &AttributeLintKind::MalformedDoc => callback(lints::MalformedDoc), - &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.decorate_lint(diag), + &AttributeLintKind::ExpectedNoArgs => callback(lints::ExpectedNoArgs), - &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.decorate_lint(diag), + &AttributeLintKind::ExpectedNameValue => callback(lints::ExpectedNameValue), &AttributeLintKind::MalformedOnUnimplementedAttr { span } => { - lints::MalformedOnUnimplementedAttrLint { span }.decorate_lint(diag) + callback(lints::MalformedOnUnimplementedAttrLint { span }) } &AttributeLintKind::MalformedOnConstAttr { span } => { - lints::MalformedOnConstAttrLint { span }.decorate_lint(diag) + callback(lints::MalformedOnConstAttrLint { span }) } AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning { FormatWarning::PositionalArgument { .. } => { - lints::DisallowedPositionalArgument.decorate_lint(diag) - } - FormatWarning::InvalidSpecifier { .. } => { - lints::InvalidFormatSpecifier.decorate_lint(diag) + callback(lints::DisallowedPositionalArgument) } + FormatWarning::InvalidSpecifier { .. } => callback(lints::InvalidFormatSpecifier), }, AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => { - lints::WrappedParserError { description, label, span: *span }.decorate_lint(diag) + callback(lints::WrappedParserError { description, label, span: *span }) } &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => { - lints::IgnoredDiagnosticOption { option_name, first_span, later_span } - .decorate_lint(diag) + callback(lints::IgnoredDiagnosticOption { option_name, first_span, later_span }) } &AttributeLintKind::MissingOptionsForOnUnimplemented => { - lints::MissingOptionsForOnUnimplementedAttr.decorate_lint(diag) + callback(lints::MissingOptionsForOnUnimplementedAttr) } &AttributeLintKind::MissingOptionsForOnConst => { - lints::MissingOptionsForOnConstAttr.decorate_lint(diag) + callback(lints::MissingOptionsForOnConstAttr) } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0461d19d544c6..03aead778727f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -11,7 +11,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::VisitorExt; -use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::inhabitedness::InhabitedPredicate; use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt}; use rustc_session::Session; @@ -2710,7 +2710,7 @@ pub(crate) struct UnexpectedCfgCargoMacroHelp { pub crate_name: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unexpected `cfg` condition name: `{$name}`")] pub(crate) struct UnexpectedCfgName { #[subdiagnostic] @@ -2857,7 +2857,7 @@ pub(crate) mod unexpected_cfg_name { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "unexpected `cfg` condition value: {$has_value -> [true] `{$value}` @@ -2992,7 +2992,7 @@ pub(crate) mod unexpected_cfg_value { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("extern crate `{$extern_crate}` is unused in crate `{$local_crate}`")] #[help("remove the dependency or add `use {$extern_crate} as _;` to the crate root")] pub(crate) struct UnusedCrateDependency { @@ -3001,7 +3001,7 @@ pub(crate) struct UnusedCrateDependency { } // FIXME(jdonszelmann): duplicated in rustc_attr_parsing, should be moved there completely. -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "{$num_suggestions -> [1] attribute must be of the form {$suggestions} @@ -3016,7 +3016,7 @@ pub(crate) struct IllFormedAttributeInput { pub docs: &'static str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unicode codepoint changing visible direction of text present in comment")] #[note( "these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen" @@ -3056,7 +3056,7 @@ pub(crate) struct UnicodeTextFlowSuggestion { pub spans: Vec, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition" )] @@ -3075,14 +3075,14 @@ pub(crate) struct AbsPathWithModuleSugg { pub replacement: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("hidden lifetime parameters in types are deprecated")] pub(crate) struct ElidedLifetimesInPaths { #[subdiagnostic] pub subdiag: ElidedLifetimeInPathSubdiag, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "{$num_snippets -> [one] unused import: {$span_snippets} @@ -3126,7 +3126,7 @@ pub(crate) enum UnusedImportsSugg { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the item `{$ident}` is imported redundantly")] pub(crate) struct RedundantImport { #[subdiagnostic] @@ -3147,7 +3147,7 @@ pub(crate) enum RedundantImportSub { DefinedPrelude(#[primary_span] Span), } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum PatternsInFnsWithoutBody { #[diag("patterns aren't allowed in foreign function declarations")] Foreign { @@ -3174,7 +3174,7 @@ pub(crate) struct PatternsInFnsWithoutBodySub { pub ident: Ident, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("prefix `{$prefix}` is unknown")] pub(crate) struct ReservedPrefix { #[label("unknown prefix")] @@ -3189,7 +3189,7 @@ pub(crate) struct ReservedPrefix { pub prefix: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("prefix `'r` is reserved")] pub(crate) struct RawPrefix { #[label("reserved prefix")] @@ -3202,7 +3202,7 @@ pub(crate) struct RawPrefix { pub suggestion: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression" )] @@ -3220,7 +3220,7 @@ pub(crate) struct BreakWithLabelAndLoopSub { pub right: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("where clause not allowed here")] #[note("see issue #89122 for more information")] pub(crate) struct DeprecatedWhereClauseLocation { @@ -3249,7 +3249,7 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lifetime parameter `{$ident}` only used once")] pub(crate) struct SingleUseLifetime { #[label("this lifetime...")] @@ -3273,7 +3273,7 @@ pub(crate) struct SingleUseLifetimeSugg { pub replace_lt: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lifetime parameter `{$ident}` never used")] pub(crate) struct UnusedLifetime { #[suggestion("elide the unused lifetime", code = "", applicability = "machine-applicable")] @@ -3282,7 +3282,7 @@ pub(crate) struct UnusedLifetime { pub ident: Ident, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("named argument `{$named_arg_name}` is not used by name")] pub(crate) struct NamedArgumentUsedPositionally { #[label("this named argument is referred to by position in formatting string")] @@ -3301,7 +3301,7 @@ pub(crate) struct NamedArgumentUsedPositionally { pub named_arg_name: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("ambiguous glob re-exports")] pub(crate) struct AmbiguousGlobReexports { #[label("the name `{$name}` in the {$namespace} namespace is first re-exported here")] @@ -3313,7 +3313,7 @@ pub(crate) struct AmbiguousGlobReexports { pub namespace: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("private item shadows public glob re-export")] pub(crate) struct HiddenGlobReexports { #[note( @@ -3327,7 +3327,7 @@ pub(crate) struct HiddenGlobReexports { pub namespace: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unnecessary qualification")] pub(crate) struct UnusedQualifications { #[suggestion( @@ -3339,7 +3339,7 @@ pub(crate) struct UnusedQualifications { pub removal_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "{$elided -> [true] `&` without an explicit lifetime name cannot be used here @@ -3405,7 +3405,7 @@ pub(crate) enum MutRefSugg { #[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")] pub(crate) struct UnqualifiedLocalImportsDiag; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("will be parsed as a guarded string in Rust 2024")] pub(crate) struct ReservedString { #[suggestion( @@ -3416,7 +3416,7 @@ pub(crate) struct ReservedString { pub suggestion: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("reserved token in Rust 2024")] pub(crate) struct ReservedMultihash { #[suggestion( @@ -3625,7 +3625,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unused attribute")] #[note( "{$valid_without_list -> @@ -3647,7 +3647,7 @@ pub(crate) struct EmptyAttributeList { pub valid_without_list: bool, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`#[{$name}]` attribute cannot be used on {$target}")] #[warning( "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" @@ -3667,7 +3667,7 @@ pub(crate) struct InvalidTargetLint { pub attr_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "{$is_used_as_inner -> [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]` @@ -3682,7 +3682,7 @@ pub(crate) struct InvalidAttrStyle { pub target: &'static str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unused attribute")] pub(crate) struct UnusedDuplicate { #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] @@ -3695,28 +3695,28 @@ pub(crate) struct UnusedDuplicate { pub warning: bool, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("malformed `doc` attribute input")] #[warning( "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" )] pub(crate) struct MalformedDoc; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("didn't expect any arguments here")] #[warning( "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" )] pub(crate) struct ExpectedNoArgs; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("expected this to be of the form `... = \"...\"`")] #[warning( "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" )] pub(crate) struct ExpectedNameValue; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unsafe attribute used without unsafe")] pub(crate) struct UnsafeAttrOutsideUnsafeLint { #[label("usage of unsafe attribute")] @@ -3734,7 +3734,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { pub right: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("visibility qualifiers have no effect on `const _` declarations")] #[note("`const _` does not declare a name, so there is nothing for the qualifier to apply to")] pub(crate) struct UnusedVisibility { @@ -3747,38 +3747,38 @@ pub(crate) struct UnusedVisibility { pub span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("doc alias is duplicated")] pub(crate) struct DocAliasDuplicated { #[label("first defined here")] pub first_defn: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`")] pub(crate) struct DocAutoCfgExpectsHideOrShow; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("there exists a built-in attribute with the same name")] pub(crate) struct AmbiguousDeriveHelpers; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/value items")] pub(crate) struct DocAutoCfgHideShowUnexpectedItem { pub attr_name: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`#![doc(auto_cfg({$attr_name}(...)))]` expects a list of items")] pub(crate) struct DocAutoCfgHideShowExpectsList { pub attr_name: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("invalid `doc` attribute")] pub(crate) struct DocInvalid; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown `doc` attribute `include`")] pub(crate) struct DocUnknownInclude { pub inner: &'static str, @@ -3790,7 +3790,7 @@ pub(crate) struct DocUnknownInclude { pub sugg: (Span, Applicability), } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown `doc` attribute `spotlight`")] #[note("`doc(spotlight)` was renamed to `doc(notable_trait)`")] #[note("`doc(spotlight)` is now a no-op")] @@ -3804,7 +3804,7 @@ pub(crate) struct DocUnknownSpotlight { pub sugg_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown `doc` attribute `{$name}`")] #[note( "`doc` attribute `{$name}` no longer functions; see issue #44136 " @@ -3816,7 +3816,7 @@ pub(crate) struct DocUnknownPasses { pub note_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown `doc` attribute `plugins`")] #[note( "`doc` attribute `plugins` no longer functions; see issue #44136 and CVE-2018-1000622 " @@ -3827,42 +3827,42 @@ pub(crate) struct DocUnknownPlugins { pub label_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown `doc` attribute `{$name}`")] pub(crate) struct DocUnknownAny { pub name: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("expected boolean for `#[doc(auto_cfg = ...)]`")] pub(crate) struct DocAutoCfgWrongLiteral; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`#[doc(test(...)]` takes a list of attributes")] pub(crate) struct DocTestTakesList; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unknown `doc(test)` attribute `{$name}`")] pub(crate) struct DocTestUnknown { pub name: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`#![doc(test(...)]` does not take a literal")] pub(crate) struct DocTestLiteral; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("this attribute can only be applied at the crate level")] #[note( "read for more information" )] pub(crate) struct AttrCrateLevelOnly; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")] pub(crate) struct DoNotRecommendDoesNotExpectArgs; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("invalid `crate_type` value")] pub(crate) struct UnknownCrateTypes { #[subdiagnostic] @@ -3877,14 +3877,14 @@ pub(crate) struct UnknownCrateTypesSuggestion { pub snippet: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unreachable configuration predicate")] pub(crate) struct UnreachableCfgSelectPredicate { #[label("this configuration predicate is never reached")] pub span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unreachable configuration predicate")] pub(crate) struct UnreachableCfgSelectPredicateWildcard { #[label("this configuration predicate is never reached")] @@ -3894,19 +3894,19 @@ pub(crate) struct UnreachableCfgSelectPredicateWildcard { pub wildcard_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("positional format arguments are not allowed here")] #[help( "only named format arguments with the name of one of the generic types are allowed in this context" )] pub(crate) struct DisallowedPositionalArgument; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("invalid format specifier")] #[help("no format specifier are supported in this position")] pub(crate) struct InvalidFormatSpecifier; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$description}")] pub(crate) struct WrappedParserError<'a> { pub description: &'a str, @@ -3915,7 +3915,7 @@ pub(crate) struct WrappedParserError<'a> { pub label: &'a str, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")] pub(crate) struct IgnoredDiagnosticOption { pub option_name: Symbol, @@ -3925,17 +3925,17 @@ pub(crate) struct IgnoredDiagnosticOption { pub later_span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("missing options for `on_unimplemented` attribute")] #[help("at least one of the `message`, `note` and `label` options are expected")] pub(crate) struct MissingOptionsForOnUnimplementedAttr; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("missing options for `on_const` attribute")] #[help("at least one of the `message`, `note` and `label` options are expected")] pub(crate) struct MissingOptionsForOnConstAttr; -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("malformed `on_unimplemented` attribute")] #[help("only `message`, `note` and `label` are allowed as options")] pub(crate) struct MalformedOnUnimplementedAttrLint { @@ -3943,7 +3943,7 @@ pub(crate) struct MalformedOnUnimplementedAttrLint { pub span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("malformed `on_const` attribute")] #[help("only `message`, `note` and `label` are allowed as options")] pub(crate) struct MalformedOnConstAttrLint { From f91a9ff6fed4c3f2deda2785db3fc2b4eef39bba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 26 Feb 2026 21:37:48 +0100 Subject: [PATCH 3/6] Update `decorate_builtin_lint` to use `Diagnostic` instead of `LintDiagnostic` --- compiler/rustc_hir_analysis/src/lib.rs | 32 +- compiler/rustc_lint/src/early.rs | 35 +- compiler/rustc_lint/src/early/diagnostics.rs | 380 ++++++++++-------- compiler/rustc_lint/src/lib.rs | 2 +- src/librustdoc/lib.rs | 36 +- .../consts/assoc-const-elided-lifetime.stderr | 8 +- .../elided-lifetime.stderr | 8 +- .../generic-associated-const.stderr | 4 +- .../static-trait-impl.stderr | 4 +- 9 files changed, 303 insertions(+), 206 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 40e79234d0201..910c472ba83f4 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -149,20 +149,30 @@ pub fn provide(providers: &mut Providers) { } fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) { + struct DiagEmitter<'tcx> { + hir_id: rustc_hir::HirId, + tcx: TyCtxt<'tcx>, + span: Span, + } + + impl rustc_lint::EmitDiag for DiagEmitter<'_> { + fn emit( + &self, + lint: &'static rustc_lint::Lint, + diag: impl for<'a> rustc_errors::Diagnostic<'a, ()>, + ) { + self.tcx.emit_node_span_lint(lint, self.hir_id, self.span, diag); + } + } + match lint { DelayedLint::AttributeParsing(attribute_lint) => { - tcx.node_span_lint( + rustc_lint::decorate_attribute_lint( + &DiagEmitter { hir_id: attribute_lint.id, tcx, span: attribute_lint.span }, + tcx.sess, + Some(tcx), + &attribute_lint.kind, attribute_lint.lint_id.lint, - attribute_lint.id, - attribute_lint.span, - |diag| { - rustc_lint::decorate_attribute_lint( - tcx.sess, - Some(tcx), - &attribute_lint.kind, - diag, - ); - }, ); } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 1c205035934b5..6d87a488373d5 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -7,7 +7,7 @@ use rustc_ast::visit::{self as ast_visit, Visitor, walk_list}; use rustc_ast::{self as ast, AttrVec, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; +use rustc_errors::{BufferedEarlyLint, DecorateDiagCompat, Diagnostic, LintBuffer, MultiSpan}; use rustc_feature::Features; use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; @@ -15,6 +15,7 @@ use rustc_session::lint::LintPass; use rustc_span::{Ident, Span}; use tracing::debug; +use crate::Lint; use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; @@ -32,16 +33,40 @@ pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> { pass: T, } +pub trait EmitDiag { + fn emit(&self, lint: &'static Lint, diag: impl for<'a> Diagnostic<'a, ()>); +} + +struct DiagEmitter<'a, 'b> { + ctx: &'a EarlyContext<'b>, + span: Option, +} + +impl EmitDiag for DiagEmitter<'_, '_> { + fn emit(&self, lint: &'static Lint, diag: impl for<'a> Diagnostic<'a, ()>) { + self.ctx.opt_span_diag_lint(lint, self.span.clone(), diag); + } +} + impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; - self.context.opt_span_diag_lint(lint_id.lint, span, |diag| match diagnostic { + match diagnostic { DecorateDiagCompat::Builtin(b) => { - diagnostics::decorate_builtin_lint(self.context.sess(), self.tcx, b, diag); + diagnostics::decorate_builtin_lint( + &DiagEmitter { ctx: &self.context, span }, + self.context.sess(), + self.tcx, + b, + lint_id.lint, + ); } - DecorateDiagCompat::Dynamic(d) => d.decorate_lint_box(diag), - }); + DecorateDiagCompat::Dynamic(d) => { + self.context + .opt_span_lint(lint_id.lint, span, |diag| d.decorate_lint_box(diag)); + } + } } } diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index b5a5dce681d07..7ce6c97410aff 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -1,9 +1,7 @@ use std::borrow::Cow; use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; -use rustc_errors::{ - Applicability, Diag, DiagArgValue, LintDiagnostic, elided_lifetime_in_path_suggestion, -}; +use rustc_errors::{Applicability, DiagArgValue, elided_lifetime_in_path_suggestion}; use rustc_hir::lints::{AttributeLintKind, FormatWarning}; use rustc_middle::middle::stability; use rustc_middle::ty::TyCtxt; @@ -12,15 +10,16 @@ use rustc_session::lint::BuiltinLintDiag; use rustc_span::BytePos; use tracing::debug; -use crate::lints; +use crate::{EmitDiag, Lint, lints}; mod check_cfg; -pub fn decorate_builtin_lint)>( +pub fn decorate_builtin_lint( + ctx: &D, sess: &Session, tcx: Option>, diagnostic: BuiltinLintDiag, - callback: F, + lint: &'static Lint, ) { match diagnostic { BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { @@ -41,12 +40,15 @@ pub fn decorate_builtin_lint)>( spans: spans.iter().map(|(_c, span)| *span).collect(), }); - callback(lints::UnicodeTextFlow { - comment_span, - characters, - suggestions, - num_codepoints: spans.len(), - }); + ctx.emit( + lint, + lints::UnicodeTextFlow { + comment_span, + characters, + suggestions, + num_codepoints: spans.len(), + }, + ); } BuiltinLintDiag::AbsPathWithModule(mod_span) => { let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) { @@ -59,20 +61,30 @@ pub fn decorate_builtin_lint)>( } Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), }; - callback(lints::AbsPathWithModule { - sugg: lints::AbsPathWithModuleSugg { span: mod_span, applicability, replacement }, - }); + ctx.emit( + lint, + lints::AbsPathWithModule { + sugg: lints::AbsPathWithModuleSugg { + span: mod_span, + applicability, + replacement, + }, + }, + ); } BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - callback(lints::ElidedLifetimesInPaths { - subdiag: elided_lifetime_in_path_suggestion( - sess.source_map(), - n, - path_span, - incl_angl_brckt, - insertion_span, - ), - }); + ctx.emit( + lint, + lints::ElidedLifetimesInPaths { + subdiag: elided_lifetime_in_path_suggestion( + sess.source_map(), + n, + path_span, + incl_angl_brckt, + insertion_span, + ), + }, + ); } BuiltinLintDiag::UnusedImports { remove_whole_use, @@ -89,14 +101,17 @@ pub fn decorate_builtin_lint)>( let test_module_span = test_module_span.map(|span| sess.source_map().guess_head_span(span)); - callback(lints::UnusedImports { - sugg, - test_module_span, - num_snippets: span_snippets.len(), - span_snippets: DiagArgValue::StrListSepByAnd( - span_snippets.into_iter().map(Cow::Owned).collect(), - ), - }); + ctx.emit( + lint, + lints::UnusedImports { + sugg, + test_module_span, + num_snippets: span_snippets.len(), + span_snippets: DiagArgValue::StrListSepByAnd( + span_snippets.into_iter().map(Cow::Owned).collect(), + ), + }, + ); } BuiltinLintDiag::RedundantImport(spans, ident) => { let subs = spans @@ -110,7 +125,7 @@ pub fn decorate_builtin_lint)>( })(span) }) .collect(); - callback(lints::RedundantImport { subs, ident }); + ctx.emit(lint, lints::RedundantImport { subs, ident }); } BuiltinLintDiag::DeprecatedMacro { suggestion, @@ -125,46 +140,55 @@ pub fn decorate_builtin_lint)>( suggestion, }); - callback(stability::Deprecated { - sub, - kind: "macro".to_owned(), - path, - note, - since_kind, - }); + ctx.emit( + lint, + stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }, + ); } BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; - callback(if is_foreign { - lints::PatternsInFnsWithoutBody::Foreign { sub } - } else { - lints::PatternsInFnsWithoutBody::Bodiless { sub } - }); + ctx.emit( + lint, + if is_foreign { + lints::PatternsInFnsWithoutBody::Foreign { sub } + } else { + lints::PatternsInFnsWithoutBody::Bodiless { sub } + }, + ); } BuiltinLintDiag::ReservedPrefix(label_span, prefix) => { - callback(lints::ReservedPrefix { - label: label_span, - suggestion: label_span.shrink_to_hi(), - prefix, - }); + ctx.emit( + lint, + lints::ReservedPrefix { + label: label_span, + suggestion: label_span.shrink_to_hi(), + prefix, + }, + ); } BuiltinLintDiag::RawPrefix(label_span) => { - callback(lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }); + ctx.emit( + lint, + lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }, + ); } BuiltinLintDiag::ReservedString { is_string, suggestion } => { if is_string { - callback(lints::ReservedString { suggestion }); + ctx.emit(lint, lints::ReservedString { suggestion }); } else { - callback(lints::ReservedMultihash { suggestion }); + ctx.emit(lint, lints::ReservedMultihash { suggestion }); } } BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => { - callback(lints::BreakWithLabelAndLoop { - sub: lints::BreakWithLabelAndLoopSub { - left: sugg_span.shrink_to_lo(), - right: sugg_span.shrink_to_hi(), + ctx.emit( + lint, + lints::BreakWithLabelAndLoop { + sub: lints::BreakWithLabelAndLoopSub { + left: sugg_span.shrink_to_lo(), + right: sugg_span.shrink_to_hi(), + }, }, - }); + ); } BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { let suggestion = match sugg { @@ -175,7 +199,7 @@ pub fn decorate_builtin_lint)>( }, None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }, }; - callback(lints::DeprecatedWhereClauseLocation { suggestion }); + ctx.emit(lint, lints::DeprecatedWhereClauseLocation { suggestion }); } BuiltinLintDiag::SingleUseLifetime { param_span, @@ -202,10 +226,10 @@ pub fn decorate_builtin_lint)>( None }; - callback(lints::SingleUseLifetime { suggestion, param_span, use_span, ident }); + ctx.emit(lint, lints::SingleUseLifetime { suggestion, param_span, use_span, ident }); } BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { - callback(lints::UnusedLifetime { deletion_span, ident }); + ctx.emit(lint, lints::UnusedLifetime { deletion_span, ident }); } BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, @@ -233,13 +257,16 @@ pub fn decorate_builtin_lint)>( (None, String::new()) }; - callback(lints::NamedArgumentUsedPositionally { - named_arg_sp, - position_label_sp: position_sp_for_msg, - suggestion, - name, - named_arg_name, - }); + ctx.emit( + lint, + lints::NamedArgumentUsedPositionally { + named_arg_sp, + position_label_sp: position_sp_for_msg, + suggestion, + name, + named_arg_name, + }, + ); } BuiltinLintDiag::AmbiguousGlobReexports { name, @@ -247,12 +274,15 @@ pub fn decorate_builtin_lint)>( first_reexport_span, duplicate_reexport_span, } => { - callback(lints::AmbiguousGlobReexports { - first_reexport: first_reexport_span, - duplicate_reexport: duplicate_reexport_span, - name, - namespace, - }); + ctx.emit( + lint, + lints::AmbiguousGlobReexports { + first_reexport: first_reexport_span, + duplicate_reexport: duplicate_reexport_span, + name, + namespace, + }, + ); } BuiltinLintDiag::HiddenGlobReexports { name, @@ -260,16 +290,19 @@ pub fn decorate_builtin_lint)>( glob_reexport_span, private_item_span, } => { - callback(lints::HiddenGlobReexports { - glob_reexport: glob_reexport_span, - private_item: private_item_span, - - name, - namespace, - }); + ctx.emit( + lint, + lints::HiddenGlobReexports { + glob_reexport: glob_reexport_span, + private_item: private_item_span, + + name, + namespace, + }, + ); } BuiltinLintDiag::UnusedQualifications { removal_span } => { - callback(lints::UnusedQualifications { removal_span }); + ctx.emit(lint, lints::UnusedQualifications { removal_span }); } BuiltinLintDiag::AssociatedConstElidedLifetime { elided, @@ -278,57 +311,67 @@ pub fn decorate_builtin_lint)>( } => { let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; let code = if elided { "'static " } else { "'static" }; - callback(lints::AssociatedConstElidedLifetime { - span: lt_span, - code, - elided, - lifetimes_in_scope, - }); + ctx.emit( + lint, + lints::AssociatedConstElidedLifetime { + span: lt_span, + code, + elided, + lifetimes_in_scope, + }, + ); } BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span { Some(wildcard_span) => { - callback(lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }) + ctx.emit(lint, lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }) } - None => callback(lints::UnreachableCfgSelectPredicate { span }), + None => ctx.emit(lint, lints::UnreachableCfgSelectPredicate { span }), }, BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { - callback(lints::UnusedCrateDependency { extern_crate, local_crate }) + ctx.emit(lint, lints::UnusedCrateDependency { extern_crate, local_crate }) + } + BuiltinLintDiag::UnusedVisibility(span) => ctx.emit(lint, lints::UnusedVisibility { span }), + BuiltinLintDiag::AttributeLint(kind) => { + decorate_attribute_lint(ctx, sess, tcx, &kind, lint) } - BuiltinLintDiag::UnusedVisibility(span) => callback(lints::UnusedVisibility { span }), - BuiltinLintDiag::AttributeLint(kind) => decorate_attribute_lint(sess, tcx, &kind, callback), } } -pub fn decorate_attribute_lint)>( +pub fn decorate_attribute_lint( + ctx: &D, sess: &Session, tcx: Option>, kind: &AttributeLintKind, - callback: F, + lint: &'static Lint, ) { match kind { &AttributeLintKind::UnusedDuplicate { this, other, warning } => { - callback(lints::UnusedDuplicate { this, other, warning }) + ctx.emit(lint, lints::UnusedDuplicate { this, other, warning }) } - AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => { - callback(lints::IllFormedAttributeInput { + AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => ctx.emit( + lint, + lints::IllFormedAttributeInput { num_suggestions: suggestions.len(), suggestions: DiagArgValue::StrListSepByAnd( suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), ), has_docs: docs.is_some(), docs: docs.unwrap_or(""), - }) - } - AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => { - callback(lints::EmptyAttributeList { - attr_span: *first_span, - attr_path: attr_path.clone(), - valid_without_list: *valid_without_list, - }) - } - AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => { - callback(lints::InvalidTargetLint { + }, + ), + AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => ctx + .emit( + lint, + lints::EmptyAttributeList { + attr_span: *first_span, + attr_path: attr_path.clone(), + valid_without_list: *valid_without_list, + }, + ), + AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => ctx.emit( + lint, + lints::InvalidTargetLint { name: name.clone(), target, applied: DiagArgValue::StrListSepByAnd( @@ -336,119 +379,124 @@ pub fn decorate_attribute_lint)>( ), only, attr_span: *attr_span, - }) - } - &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => { - callback(lints::InvalidAttrStyle { - name: name.clone(), - is_used_as_inner, - target_span: (!is_used_as_inner).then_some(target_span), - target, - }) - } - &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => { - callback(lints::UnsafeAttrOutsideUnsafeLint { - span: attribute_name_span, - suggestion: sugg_spans - .map(|(left, right)| lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }), - }) - } + }, + ), + &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => ctx + .emit( + lint, + lints::InvalidAttrStyle { + name: name.clone(), + is_used_as_inner, + target_span: (!is_used_as_inner).then_some(target_span), + target, + }, + ), + &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => ctx + .emit( + lint, + lints::UnsafeAttrOutsideUnsafeLint { + span: attribute_name_span, + suggestion: sugg_spans.map(|(left, right)| { + lints::UnsafeAttrOutsideUnsafeSuggestion { left, right } + }), + }, + ), &AttributeLintKind::UnexpectedCfgName(name, value) => { - callback(check_cfg::unexpected_cfg_name(sess, tcx, name, value)) + ctx.emit(lint, check_cfg::unexpected_cfg_name(sess, tcx, name, value)) } &AttributeLintKind::UnexpectedCfgValue(name, value) => { - callback(check_cfg::unexpected_cfg_value(sess, tcx, name, value)) + ctx.emit(lint, check_cfg::unexpected_cfg_value(sess, tcx, name, value)) } &AttributeLintKind::DuplicateDocAlias { first_definition } => { - callback(lints::DocAliasDuplicated { first_defn: first_definition }) + ctx.emit(lint, lints::DocAliasDuplicated { first_defn: first_definition }) } &AttributeLintKind::DocAutoCfgExpectsHideOrShow => { - callback(lints::DocAutoCfgExpectsHideOrShow) + ctx.emit(lint, lints::DocAutoCfgExpectsHideOrShow) } - &AttributeLintKind::AmbiguousDeriveHelpers => callback(lints::AmbiguousDeriveHelpers), + &AttributeLintKind::AmbiguousDeriveHelpers => ctx.emit(lint, lints::AmbiguousDeriveHelpers), &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => { - callback(lints::DocAutoCfgHideShowUnexpectedItem { attr_name }) + ctx.emit(lint, lints::DocAutoCfgHideShowUnexpectedItem { attr_name }) } &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => { - callback(lints::DocAutoCfgHideShowExpectsList { attr_name }) + ctx.emit(lint, lints::DocAutoCfgHideShowExpectsList { attr_name }) } - &AttributeLintKind::DocInvalid => callback(lints::DocInvalid), + &AttributeLintKind::DocInvalid => ctx.emit(lint, lints::DocInvalid), - &AttributeLintKind::DocUnknownInclude { span, inner, value } => { - callback(lints::DocUnknownInclude { - inner, - value, - sugg: (span, Applicability::MaybeIncorrect), - }) - } + &AttributeLintKind::DocUnknownInclude { span, inner, value } => ctx.emit( + lint, + lints::DocUnknownInclude { inner, value, sugg: (span, Applicability::MaybeIncorrect) }, + ), &AttributeLintKind::DocUnknownSpotlight { span } => { - callback(lints::DocUnknownSpotlight { sugg_span: span }) + ctx.emit(lint, lints::DocUnknownSpotlight { sugg_span: span }) } &AttributeLintKind::DocUnknownPasses { name, span } => { - callback(lints::DocUnknownPasses { name, note_span: span }) + ctx.emit(lint, lints::DocUnknownPasses { name, note_span: span }) } &AttributeLintKind::DocUnknownPlugins { span } => { - callback(lints::DocUnknownPlugins { label_span: span }) + ctx.emit(lint, lints::DocUnknownPlugins { label_span: span }) } - &AttributeLintKind::DocUnknownAny { name } => callback(lints::DocUnknownAny { name }), + &AttributeLintKind::DocUnknownAny { name } => ctx.emit(lint, lints::DocUnknownAny { name }), - &AttributeLintKind::DocAutoCfgWrongLiteral => callback(lints::DocAutoCfgWrongLiteral), + &AttributeLintKind::DocAutoCfgWrongLiteral => ctx.emit(lint, lints::DocAutoCfgWrongLiteral), - &AttributeLintKind::DocTestTakesList => callback(lints::DocTestTakesList), + &AttributeLintKind::DocTestTakesList => ctx.emit(lint, lints::DocTestTakesList), - &AttributeLintKind::DocTestUnknown { name } => callback(lints::DocTestUnknown { name }), + &AttributeLintKind::DocTestUnknown { name } => { + ctx.emit(lint, lints::DocTestUnknown { name }) + } - &AttributeLintKind::DocTestLiteral => callback(lints::DocTestLiteral), + &AttributeLintKind::DocTestLiteral => ctx.emit(lint, lints::DocTestLiteral), - &AttributeLintKind::AttrCrateLevelOnly => callback(lints::AttrCrateLevelOnly), + &AttributeLintKind::AttrCrateLevelOnly => ctx.emit(lint, lints::AttrCrateLevelOnly), &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => { - callback(lints::DoNotRecommendDoesNotExpectArgs) + ctx.emit(lint, lints::DoNotRecommendDoesNotExpectArgs) } - &AttributeLintKind::CrateTypeUnknown { span, suggested } => { - callback(lints::UnknownCrateTypes { + &AttributeLintKind::CrateTypeUnknown { span, suggested } => ctx.emit( + lint, + lints::UnknownCrateTypes { sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), - }) - } + }, + ), - &AttributeLintKind::MalformedDoc => callback(lints::MalformedDoc), + &AttributeLintKind::MalformedDoc => ctx.emit(lint, lints::MalformedDoc), - &AttributeLintKind::ExpectedNoArgs => callback(lints::ExpectedNoArgs), + &AttributeLintKind::ExpectedNoArgs => ctx.emit(lint, lints::ExpectedNoArgs), - &AttributeLintKind::ExpectedNameValue => callback(lints::ExpectedNameValue), + &AttributeLintKind::ExpectedNameValue => ctx.emit(lint, lints::ExpectedNameValue), &AttributeLintKind::MalformedOnUnimplementedAttr { span } => { - callback(lints::MalformedOnUnimplementedAttrLint { span }) + ctx.emit(lint, lints::MalformedOnUnimplementedAttrLint { span }) } &AttributeLintKind::MalformedOnConstAttr { span } => { - callback(lints::MalformedOnConstAttrLint { span }) + ctx.emit(lint, lints::MalformedOnConstAttrLint { span }) } AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning { FormatWarning::PositionalArgument { .. } => { - callback(lints::DisallowedPositionalArgument) + ctx.emit(lint, lints::DisallowedPositionalArgument) } - FormatWarning::InvalidSpecifier { .. } => callback(lints::InvalidFormatSpecifier), + FormatWarning::InvalidSpecifier { .. } => ctx.emit(lint, lints::InvalidFormatSpecifier), }, AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => { - callback(lints::WrappedParserError { description, label, span: *span }) + ctx.emit(lint, lints::WrappedParserError { description, label, span: *span }) } &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => { - callback(lints::IgnoredDiagnosticOption { option_name, first_span, later_span }) + ctx.emit(lint, lints::IgnoredDiagnosticOption { option_name, first_span, later_span }) } &AttributeLintKind::MissingOptionsForOnUnimplemented => { - callback(lints::MissingOptionsForOnUnimplementedAttr) + ctx.emit(lint, lints::MissingOptionsForOnUnimplementedAttr) } &AttributeLintKind::MissingOptionsForOnConst => { - callback(lints::MissingOptionsForOnConstAttr) + ctx.emit(lint, lints::MissingOptionsForOnConstAttr) } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 34276eb76cf39..e524a66910d93 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -132,7 +132,7 @@ use unused::*; pub use builtin::{MissingDoc, SoftLints}; pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore}; pub use early::diagnostics::{decorate_attribute_lint, decorate_builtin_lint}; -pub use early::{EarlyCheckNode, check_ast_node}; +pub use early::{EarlyCheckNode, EmitDiag, check_ast_node}; pub use late::{check_crate, late_lint_mod, unerased_lint_store}; pub use levels::LintLevelsBuilder; pub use passes::{EarlyLintPass, LateLintPass}; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 541ab3d1c295e..4b659ff8f4f46 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -772,6 +772,22 @@ fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> { Ok(()) } +struct DiagEmitter<'tcx> { + hir_id: rustc_hir::HirId, + tcx: TyCtxt<'tcx>, + span: rustc_span::Span, +} + +impl rustc_lint::EmitDiag for DiagEmitter<'_> { + fn emit( + &self, + lint: &'static rustc_lint::Lint, + diag: impl for<'a> rustc_errors::Diagnostic<'a, ()>, + ) { + self.tcx.emit_node_span_lint(lint, self.hir_id, self.span, diag); + } +} + fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by @@ -912,18 +928,16 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { for lint in &delayed_lints.lints { match lint { DelayedLint::AttributeParsing(attribute_lint) => { - tcx.node_span_lint( - attribute_lint.lint_id.lint, - attribute_lint.id, - attribute_lint.span, - |diag| { - rustc_lint::decorate_attribute_lint( - tcx.sess, - Some(tcx), - &attribute_lint.kind, - diag, - ); + rustc_lint::decorate_attribute_lint( + &DiagEmitter { + hir_id: attribute_lint.id, + tcx, + span: attribute_lint.span, }, + tcx.sess, + Some(tcx), + &attribute_lint.kind, + attribute_lint.lint_id.lint, ); } } diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr index 9582152683578..6277b079bdac7 100644 --- a/tests/ui/consts/assoc-const-elided-lifetime.stderr +++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr @@ -4,13 +4,13 @@ error: `'_` cannot be used here LL | const FOO: Foo<'_> = Foo { x: PhantomData::<&()> }; | ^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 note: cannot automatically infer `'static` because of other lifetimes in scope --> $DIR/assoc-const-elided-lifetime.rs:9:6 | LL | impl<'a> Foo<'a> { | ^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 note: the lint level is defined here --> $DIR/assoc-const-elided-lifetime.rs:1:9 | @@ -28,13 +28,13 @@ error: `&` without an explicit lifetime name cannot be used here LL | const BAR: &() = &(); | ^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 note: cannot automatically infer `'static` because of other lifetimes in scope --> $DIR/assoc-const-elided-lifetime.rs:9:6 | LL | impl<'a> Foo<'a> { | ^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 help: use the `'static` lifetime | LL | const BAR: &'static () = &(); diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr index ae4a48e4e9328..370e6655d8607 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr @@ -4,13 +4,13 @@ error: `&` without an explicit lifetime name cannot be used here LL | const STATIC: &str = ""; | ^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 note: cannot automatically infer `'static` because of other lifetimes in scope --> $DIR/elided-lifetime.rs:5:10 | LL | impl Foo<'_> { | ^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 note: the lint level is defined here --> $DIR/elided-lifetime.rs:1:9 | @@ -27,13 +27,13 @@ error: `&` without an explicit lifetime name cannot be used here LL | const STATIC: &str = ""; | ^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 note: cannot automatically infer `'static` because of other lifetimes in scope --> $DIR/elided-lifetime.rs:15:18 | LL | impl Bar for Foo<'_> { | ^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 help: use the `'static` lifetime | LL | const STATIC: &'static str = ""; diff --git a/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr index 2ecab3442a96e..3680ef61e0c4c 100644 --- a/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr +++ b/tests/ui/consts/static-default-lifetime/generic-associated-const.stderr @@ -24,13 +24,13 @@ error: `&` without an explicit lifetime name cannot be used here LL | const GAC_LIFETIME<'a>: &str = ""; | ^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 note: cannot automatically infer `'static` because of other lifetimes in scope --> $DIR/generic-associated-const.rs:8:24 | LL | const GAC_LIFETIME<'a>: &str = ""; | ^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 note: the lint level is defined here --> $DIR/generic-associated-const.rs:1:9 | diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr index 2bc271dccad91..ab82515162014 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr @@ -4,13 +4,13 @@ error: `&` without an explicit lifetime name cannot be used here LL | const STATIC: &str = ""; | ^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #115010 note: cannot automatically infer `'static` because of other lifetimes in scope --> $DIR/static-trait-impl.rs:8:10 | LL | impl Bar<'_> for A { | ^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #115010 note: the lint level is defined here --> $DIR/static-trait-impl.rs:1:9 | From cd9df185df067883e6460b39ce09296b068e5276 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Feb 2026 00:09:09 +0100 Subject: [PATCH 4/6] Simplify `rustc_lint::EmitDiag` by removing `Lint` from its API --- compiler/rustc_hir_analysis/src/lib.rs | 17 +- compiler/rustc_lint/src/early.rs | 10 +- compiler/rustc_lint/src/early/diagnostics.rs | 359 ++++++++----------- src/librustdoc/lib.rs | 11 +- 4 files changed, 171 insertions(+), 226 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 910c472ba83f4..764557069205e 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -153,26 +153,27 @@ fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) { hir_id: rustc_hir::HirId, tcx: TyCtxt<'tcx>, span: Span, + lint: &'static rustc_lint::Lint, } impl rustc_lint::EmitDiag for DiagEmitter<'_> { - fn emit( - &self, - lint: &'static rustc_lint::Lint, - diag: impl for<'a> rustc_errors::Diagnostic<'a, ()>, - ) { - self.tcx.emit_node_span_lint(lint, self.hir_id, self.span, diag); + fn emit(&self, diag: impl for<'a> rustc_errors::Diagnostic<'a, ()>) { + self.tcx.emit_node_span_lint(self.lint, self.hir_id, self.span, diag); } } match lint { DelayedLint::AttributeParsing(attribute_lint) => { rustc_lint::decorate_attribute_lint( - &DiagEmitter { hir_id: attribute_lint.id, tcx, span: attribute_lint.span }, + &DiagEmitter { + hir_id: attribute_lint.id, + tcx, + span: attribute_lint.span, + lint: attribute_lint.lint_id.lint, + }, tcx.sess, Some(tcx), &attribute_lint.kind, - attribute_lint.lint_id.lint, ); } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 6d87a488373d5..c9ecdd930064c 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -34,17 +34,18 @@ pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> { } pub trait EmitDiag { - fn emit(&self, lint: &'static Lint, diag: impl for<'a> Diagnostic<'a, ()>); + fn emit(&self, diag: impl for<'a> Diagnostic<'a, ()>); } struct DiagEmitter<'a, 'b> { ctx: &'a EarlyContext<'b>, span: Option, + lint: &'static Lint, } impl EmitDiag for DiagEmitter<'_, '_> { - fn emit(&self, lint: &'static Lint, diag: impl for<'a> Diagnostic<'a, ()>) { - self.ctx.opt_span_diag_lint(lint, self.span.clone(), diag); + fn emit(&self, diag: impl for<'a> Diagnostic<'a, ()>) { + self.ctx.opt_span_diag_lint(self.lint, self.span.clone(), diag); } } @@ -55,11 +56,10 @@ impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { match diagnostic { DecorateDiagCompat::Builtin(b) => { diagnostics::decorate_builtin_lint( - &DiagEmitter { ctx: &self.context, span }, + &DiagEmitter { ctx: &self.context, span, lint: lint_id.lint }, self.context.sess(), self.tcx, b, - lint_id.lint, ); } DecorateDiagCompat::Dynamic(d) => { diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 7ce6c97410aff..0a0db43226d13 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -10,7 +10,7 @@ use rustc_session::lint::BuiltinLintDiag; use rustc_span::BytePos; use tracing::debug; -use crate::{EmitDiag, Lint, lints}; +use crate::{EmitDiag, lints}; mod check_cfg; @@ -19,7 +19,6 @@ pub fn decorate_builtin_lint( sess: &Session, tcx: Option>, diagnostic: BuiltinLintDiag, - lint: &'static Lint, ) { match diagnostic { BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { @@ -40,15 +39,12 @@ pub fn decorate_builtin_lint( spans: spans.iter().map(|(_c, span)| *span).collect(), }); - ctx.emit( - lint, - lints::UnicodeTextFlow { - comment_span, - characters, - suggestions, - num_codepoints: spans.len(), - }, - ); + ctx.emit(lints::UnicodeTextFlow { + comment_span, + characters, + suggestions, + num_codepoints: spans.len(), + }); } BuiltinLintDiag::AbsPathWithModule(mod_span) => { let (replacement, applicability) = match sess.source_map().span_to_snippet(mod_span) { @@ -61,30 +57,20 @@ pub fn decorate_builtin_lint( } Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), }; - ctx.emit( - lint, - lints::AbsPathWithModule { - sugg: lints::AbsPathWithModuleSugg { - span: mod_span, - applicability, - replacement, - }, - }, - ); + ctx.emit(lints::AbsPathWithModule { + sugg: lints::AbsPathWithModuleSugg { span: mod_span, applicability, replacement }, + }); } BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - ctx.emit( - lint, - lints::ElidedLifetimesInPaths { - subdiag: elided_lifetime_in_path_suggestion( - sess.source_map(), - n, - path_span, - incl_angl_brckt, - insertion_span, - ), - }, - ); + ctx.emit(lints::ElidedLifetimesInPaths { + subdiag: elided_lifetime_in_path_suggestion( + sess.source_map(), + n, + path_span, + incl_angl_brckt, + insertion_span, + ), + }); } BuiltinLintDiag::UnusedImports { remove_whole_use, @@ -101,17 +87,14 @@ pub fn decorate_builtin_lint( let test_module_span = test_module_span.map(|span| sess.source_map().guess_head_span(span)); - ctx.emit( - lint, - lints::UnusedImports { - sugg, - test_module_span, - num_snippets: span_snippets.len(), - span_snippets: DiagArgValue::StrListSepByAnd( - span_snippets.into_iter().map(Cow::Owned).collect(), - ), - }, - ); + ctx.emit(lints::UnusedImports { + sugg, + test_module_span, + num_snippets: span_snippets.len(), + span_snippets: DiagArgValue::StrListSepByAnd( + span_snippets.into_iter().map(Cow::Owned).collect(), + ), + }); } BuiltinLintDiag::RedundantImport(spans, ident) => { let subs = spans @@ -125,7 +108,7 @@ pub fn decorate_builtin_lint( })(span) }) .collect(); - ctx.emit(lint, lints::RedundantImport { subs, ident }); + ctx.emit(lints::RedundantImport { subs, ident }); } BuiltinLintDiag::DeprecatedMacro { suggestion, @@ -140,55 +123,46 @@ pub fn decorate_builtin_lint( suggestion, }); - ctx.emit( - lint, - stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind }, - ); + ctx.emit(stability::Deprecated { + sub, + kind: "macro".to_owned(), + path, + note, + since_kind, + }); } BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; - ctx.emit( - lint, - if is_foreign { - lints::PatternsInFnsWithoutBody::Foreign { sub } - } else { - lints::PatternsInFnsWithoutBody::Bodiless { sub } - }, - ); + ctx.emit(if is_foreign { + lints::PatternsInFnsWithoutBody::Foreign { sub } + } else { + lints::PatternsInFnsWithoutBody::Bodiless { sub } + }); } BuiltinLintDiag::ReservedPrefix(label_span, prefix) => { - ctx.emit( - lint, - lints::ReservedPrefix { - label: label_span, - suggestion: label_span.shrink_to_hi(), - prefix, - }, - ); + ctx.emit(lints::ReservedPrefix { + label: label_span, + suggestion: label_span.shrink_to_hi(), + prefix, + }); } BuiltinLintDiag::RawPrefix(label_span) => { - ctx.emit( - lint, - lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }, - ); + ctx.emit(lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() }); } BuiltinLintDiag::ReservedString { is_string, suggestion } => { if is_string { - ctx.emit(lint, lints::ReservedString { suggestion }); + ctx.emit(lints::ReservedString { suggestion }); } else { - ctx.emit(lint, lints::ReservedMultihash { suggestion }); + ctx.emit(lints::ReservedMultihash { suggestion }); } } BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => { - ctx.emit( - lint, - lints::BreakWithLabelAndLoop { - sub: lints::BreakWithLabelAndLoopSub { - left: sugg_span.shrink_to_lo(), - right: sugg_span.shrink_to_hi(), - }, + ctx.emit(lints::BreakWithLabelAndLoop { + sub: lints::BreakWithLabelAndLoopSub { + left: sugg_span.shrink_to_lo(), + right: sugg_span.shrink_to_hi(), }, - ); + }); } BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { let suggestion = match sugg { @@ -199,7 +173,7 @@ pub fn decorate_builtin_lint( }, None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }, }; - ctx.emit(lint, lints::DeprecatedWhereClauseLocation { suggestion }); + ctx.emit(lints::DeprecatedWhereClauseLocation { suggestion }); } BuiltinLintDiag::SingleUseLifetime { param_span, @@ -226,10 +200,10 @@ pub fn decorate_builtin_lint( None }; - ctx.emit(lint, lints::SingleUseLifetime { suggestion, param_span, use_span, ident }); + ctx.emit(lints::SingleUseLifetime { suggestion, param_span, use_span, ident }); } BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { - ctx.emit(lint, lints::UnusedLifetime { deletion_span, ident }); + ctx.emit(lints::UnusedLifetime { deletion_span, ident }); } BuiltinLintDiag::NamedArgumentUsedPositionally { position_sp_to_replace, @@ -257,16 +231,13 @@ pub fn decorate_builtin_lint( (None, String::new()) }; - ctx.emit( - lint, - lints::NamedArgumentUsedPositionally { - named_arg_sp, - position_label_sp: position_sp_for_msg, - suggestion, - name, - named_arg_name, - }, - ); + ctx.emit(lints::NamedArgumentUsedPositionally { + named_arg_sp, + position_label_sp: position_sp_for_msg, + suggestion, + name, + named_arg_name, + }); } BuiltinLintDiag::AmbiguousGlobReexports { name, @@ -274,15 +245,12 @@ pub fn decorate_builtin_lint( first_reexport_span, duplicate_reexport_span, } => { - ctx.emit( - lint, - lints::AmbiguousGlobReexports { - first_reexport: first_reexport_span, - duplicate_reexport: duplicate_reexport_span, - name, - namespace, - }, - ); + ctx.emit(lints::AmbiguousGlobReexports { + first_reexport: first_reexport_span, + duplicate_reexport: duplicate_reexport_span, + name, + namespace, + }); } BuiltinLintDiag::HiddenGlobReexports { name, @@ -290,19 +258,16 @@ pub fn decorate_builtin_lint( glob_reexport_span, private_item_span, } => { - ctx.emit( - lint, - lints::HiddenGlobReexports { - glob_reexport: glob_reexport_span, - private_item: private_item_span, - - name, - namespace, - }, - ); + ctx.emit(lints::HiddenGlobReexports { + glob_reexport: glob_reexport_span, + private_item: private_item_span, + + name, + namespace, + }); } BuiltinLintDiag::UnusedQualifications { removal_span } => { - ctx.emit(lint, lints::UnusedQualifications { removal_span }); + ctx.emit(lints::UnusedQualifications { removal_span }); } BuiltinLintDiag::AssociatedConstElidedLifetime { elided, @@ -311,30 +276,25 @@ pub fn decorate_builtin_lint( } => { let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; let code = if elided { "'static " } else { "'static" }; - ctx.emit( - lint, - lints::AssociatedConstElidedLifetime { - span: lt_span, - code, - elided, - lifetimes_in_scope, - }, - ); + ctx.emit(lints::AssociatedConstElidedLifetime { + span: lt_span, + code, + elided, + lifetimes_in_scope, + }); } BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span { Some(wildcard_span) => { - ctx.emit(lint, lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }) + ctx.emit(lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span }) } - None => ctx.emit(lint, lints::UnreachableCfgSelectPredicate { span }), + None => ctx.emit(lints::UnreachableCfgSelectPredicate { span }), }, BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { - ctx.emit(lint, lints::UnusedCrateDependency { extern_crate, local_crate }) - } - BuiltinLintDiag::UnusedVisibility(span) => ctx.emit(lint, lints::UnusedVisibility { span }), - BuiltinLintDiag::AttributeLint(kind) => { - decorate_attribute_lint(ctx, sess, tcx, &kind, lint) + ctx.emit(lints::UnusedCrateDependency { extern_crate, local_crate }) } + BuiltinLintDiag::UnusedVisibility(span) => ctx.emit(lints::UnusedVisibility { span }), + BuiltinLintDiag::AttributeLint(kind) => decorate_attribute_lint(ctx, sess, tcx, &kind), } } @@ -343,35 +303,29 @@ pub fn decorate_attribute_lint( sess: &Session, tcx: Option>, kind: &AttributeLintKind, - lint: &'static Lint, ) { match kind { &AttributeLintKind::UnusedDuplicate { this, other, warning } => { - ctx.emit(lint, lints::UnusedDuplicate { this, other, warning }) + ctx.emit(lints::UnusedDuplicate { this, other, warning }) } - AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => ctx.emit( - lint, - lints::IllFormedAttributeInput { + AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => { + ctx.emit(lints::IllFormedAttributeInput { num_suggestions: suggestions.len(), suggestions: DiagArgValue::StrListSepByAnd( suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), ), has_docs: docs.is_some(), docs: docs.unwrap_or(""), - }, - ), + }) + } AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => ctx - .emit( - lint, - lints::EmptyAttributeList { - attr_span: *first_span, - attr_path: attr_path.clone(), - valid_without_list: *valid_without_list, - }, - ), - AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => ctx.emit( - lint, - lints::InvalidTargetLint { + .emit(lints::EmptyAttributeList { + attr_span: *first_span, + attr_path: attr_path.clone(), + valid_without_list: *valid_without_list, + }), + AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => { + ctx.emit(lints::InvalidTargetLint { name: name.clone(), target, applied: DiagArgValue::StrListSepByAnd( @@ -379,124 +333,117 @@ pub fn decorate_attribute_lint( ), only, attr_span: *attr_span, - }, - ), + }) + } &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => ctx - .emit( - lint, - lints::InvalidAttrStyle { - name: name.clone(), - is_used_as_inner, - target_span: (!is_used_as_inner).then_some(target_span), - target, - }, - ), + .emit(lints::InvalidAttrStyle { + name: name.clone(), + is_used_as_inner, + target_span: (!is_used_as_inner).then_some(target_span), + target, + }), &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => ctx - .emit( - lint, - lints::UnsafeAttrOutsideUnsafeLint { - span: attribute_name_span, - suggestion: sugg_spans.map(|(left, right)| { - lints::UnsafeAttrOutsideUnsafeSuggestion { left, right } - }), - }, - ), + .emit(lints::UnsafeAttrOutsideUnsafeLint { + span: attribute_name_span, + suggestion: sugg_spans + .map(|(left, right)| lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }), + }), &AttributeLintKind::UnexpectedCfgName(name, value) => { - ctx.emit(lint, check_cfg::unexpected_cfg_name(sess, tcx, name, value)) + ctx.emit(check_cfg::unexpected_cfg_name(sess, tcx, name, value)) } &AttributeLintKind::UnexpectedCfgValue(name, value) => { - ctx.emit(lint, check_cfg::unexpected_cfg_value(sess, tcx, name, value)) + ctx.emit(check_cfg::unexpected_cfg_value(sess, tcx, name, value)) } &AttributeLintKind::DuplicateDocAlias { first_definition } => { - ctx.emit(lint, lints::DocAliasDuplicated { first_defn: first_definition }) + ctx.emit(lints::DocAliasDuplicated { first_defn: first_definition }) } &AttributeLintKind::DocAutoCfgExpectsHideOrShow => { - ctx.emit(lint, lints::DocAutoCfgExpectsHideOrShow) + ctx.emit(lints::DocAutoCfgExpectsHideOrShow) } - &AttributeLintKind::AmbiguousDeriveHelpers => ctx.emit(lint, lints::AmbiguousDeriveHelpers), + &AttributeLintKind::AmbiguousDeriveHelpers => ctx.emit(lints::AmbiguousDeriveHelpers), &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => { - ctx.emit(lint, lints::DocAutoCfgHideShowUnexpectedItem { attr_name }) + ctx.emit(lints::DocAutoCfgHideShowUnexpectedItem { attr_name }) } &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => { - ctx.emit(lint, lints::DocAutoCfgHideShowExpectsList { attr_name }) + ctx.emit(lints::DocAutoCfgHideShowExpectsList { attr_name }) } - &AttributeLintKind::DocInvalid => ctx.emit(lint, lints::DocInvalid), + &AttributeLintKind::DocInvalid => ctx.emit(lints::DocInvalid), - &AttributeLintKind::DocUnknownInclude { span, inner, value } => ctx.emit( - lint, - lints::DocUnknownInclude { inner, value, sugg: (span, Applicability::MaybeIncorrect) }, - ), + &AttributeLintKind::DocUnknownInclude { span, inner, value } => { + ctx.emit(lints::DocUnknownInclude { + inner, + value, + sugg: (span, Applicability::MaybeIncorrect), + }) + } &AttributeLintKind::DocUnknownSpotlight { span } => { - ctx.emit(lint, lints::DocUnknownSpotlight { sugg_span: span }) + ctx.emit(lints::DocUnknownSpotlight { sugg_span: span }) } &AttributeLintKind::DocUnknownPasses { name, span } => { - ctx.emit(lint, lints::DocUnknownPasses { name, note_span: span }) + ctx.emit(lints::DocUnknownPasses { name, note_span: span }) } &AttributeLintKind::DocUnknownPlugins { span } => { - ctx.emit(lint, lints::DocUnknownPlugins { label_span: span }) + ctx.emit(lints::DocUnknownPlugins { label_span: span }) } - &AttributeLintKind::DocUnknownAny { name } => ctx.emit(lint, lints::DocUnknownAny { name }), + &AttributeLintKind::DocUnknownAny { name } => ctx.emit(lints::DocUnknownAny { name }), - &AttributeLintKind::DocAutoCfgWrongLiteral => ctx.emit(lint, lints::DocAutoCfgWrongLiteral), + &AttributeLintKind::DocAutoCfgWrongLiteral => ctx.emit(lints::DocAutoCfgWrongLiteral), - &AttributeLintKind::DocTestTakesList => ctx.emit(lint, lints::DocTestTakesList), + &AttributeLintKind::DocTestTakesList => ctx.emit(lints::DocTestTakesList), - &AttributeLintKind::DocTestUnknown { name } => { - ctx.emit(lint, lints::DocTestUnknown { name }) - } + &AttributeLintKind::DocTestUnknown { name } => ctx.emit(lints::DocTestUnknown { name }), - &AttributeLintKind::DocTestLiteral => ctx.emit(lint, lints::DocTestLiteral), + &AttributeLintKind::DocTestLiteral => ctx.emit(lints::DocTestLiteral), - &AttributeLintKind::AttrCrateLevelOnly => ctx.emit(lint, lints::AttrCrateLevelOnly), + &AttributeLintKind::AttrCrateLevelOnly => ctx.emit(lints::AttrCrateLevelOnly), &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => { - ctx.emit(lint, lints::DoNotRecommendDoesNotExpectArgs) + ctx.emit(lints::DoNotRecommendDoesNotExpectArgs) } - &AttributeLintKind::CrateTypeUnknown { span, suggested } => ctx.emit( - lint, - lints::UnknownCrateTypes { + &AttributeLintKind::CrateTypeUnknown { span, suggested } => { + ctx.emit(lints::UnknownCrateTypes { sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), - }, - ), + }) + } - &AttributeLintKind::MalformedDoc => ctx.emit(lint, lints::MalformedDoc), + &AttributeLintKind::MalformedDoc => ctx.emit(lints::MalformedDoc), - &AttributeLintKind::ExpectedNoArgs => ctx.emit(lint, lints::ExpectedNoArgs), + &AttributeLintKind::ExpectedNoArgs => ctx.emit(lints::ExpectedNoArgs), - &AttributeLintKind::ExpectedNameValue => ctx.emit(lint, lints::ExpectedNameValue), + &AttributeLintKind::ExpectedNameValue => ctx.emit(lints::ExpectedNameValue), &AttributeLintKind::MalformedOnUnimplementedAttr { span } => { - ctx.emit(lint, lints::MalformedOnUnimplementedAttrLint { span }) + ctx.emit(lints::MalformedOnUnimplementedAttrLint { span }) } &AttributeLintKind::MalformedOnConstAttr { span } => { - ctx.emit(lint, lints::MalformedOnConstAttrLint { span }) + ctx.emit(lints::MalformedOnConstAttrLint { span }) } AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning { FormatWarning::PositionalArgument { .. } => { - ctx.emit(lint, lints::DisallowedPositionalArgument) + ctx.emit(lints::DisallowedPositionalArgument) } - FormatWarning::InvalidSpecifier { .. } => ctx.emit(lint, lints::InvalidFormatSpecifier), + FormatWarning::InvalidSpecifier { .. } => ctx.emit(lints::InvalidFormatSpecifier), }, AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => { - ctx.emit(lint, lints::WrappedParserError { description, label, span: *span }) + ctx.emit(lints::WrappedParserError { description, label, span: *span }) } &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => { - ctx.emit(lint, lints::IgnoredDiagnosticOption { option_name, first_span, later_span }) + ctx.emit(lints::IgnoredDiagnosticOption { option_name, first_span, later_span }) } &AttributeLintKind::MissingOptionsForOnUnimplemented => { - ctx.emit(lint, lints::MissingOptionsForOnUnimplementedAttr) + ctx.emit(lints::MissingOptionsForOnUnimplementedAttr) } &AttributeLintKind::MissingOptionsForOnConst => { - ctx.emit(lint, lints::MissingOptionsForOnConstAttr) + ctx.emit(lints::MissingOptionsForOnConstAttr) } } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4b659ff8f4f46..0c9f4b5d202f9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -776,15 +776,12 @@ struct DiagEmitter<'tcx> { hir_id: rustc_hir::HirId, tcx: TyCtxt<'tcx>, span: rustc_span::Span, + lint: &'static rustc_lint::Lint, } impl rustc_lint::EmitDiag for DiagEmitter<'_> { - fn emit( - &self, - lint: &'static rustc_lint::Lint, - diag: impl for<'a> rustc_errors::Diagnostic<'a, ()>, - ) { - self.tcx.emit_node_span_lint(lint, self.hir_id, self.span, diag); + fn emit(&self, diag: impl for<'a> rustc_errors::Diagnostic<'a, ()>) { + self.tcx.emit_node_span_lint(self.lint, self.hir_id, self.span, diag); } } @@ -933,11 +930,11 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { hir_id: attribute_lint.id, tcx, span: attribute_lint.span, + lint: attribute_lint.lint_id.lint, }, tcx.sess, Some(tcx), &attribute_lint.kind, - attribute_lint.lint_id.lint, ); } } From 6f6a9d52f5b8922e0e9e74dcb215a0b890fd0909 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Feb 2026 00:18:06 +0100 Subject: [PATCH 5/6] Remove duplicated code for delayed lints between `rustc_hir_analysis` and `rustdoc` --- compiler/rustc_hir_analysis/src/lib.rs | 2 +- src/librustdoc/lib.rs | 30 +------------------------- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 764557069205e..1641a7c31ec32 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -148,7 +148,7 @@ pub fn provide(providers: &mut Providers) { }; } -fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) { +pub fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) { struct DiagEmitter<'tcx> { hir_id: rustc_hir::HirId, tcx: TyCtxt<'tcx>, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0c9f4b5d202f9..8cad0210ea346 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -74,7 +74,6 @@ use std::process::ExitCode; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::lints::DelayedLint; use rustc_interface::interface; use rustc_middle::ty::TyCtxt; use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option}; @@ -772,19 +771,6 @@ fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> { Ok(()) } -struct DiagEmitter<'tcx> { - hir_id: rustc_hir::HirId, - tcx: TyCtxt<'tcx>, - span: rustc_span::Span, - lint: &'static rustc_lint::Lint, -} - -impl rustc_lint::EmitDiag for DiagEmitter<'_> { - fn emit(&self, diag: impl for<'a> rustc_errors::Diagnostic<'a, ()>) { - self.tcx.emit_node_span_lint(self.lint, self.hir_id, self.span, diag); - } -} - fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by @@ -923,21 +909,7 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { for owner_id in tcx.hir_crate_items(()).delayed_lint_items() { if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) { for lint in &delayed_lints.lints { - match lint { - DelayedLint::AttributeParsing(attribute_lint) => { - rustc_lint::decorate_attribute_lint( - &DiagEmitter { - hir_id: attribute_lint.id, - tcx, - span: attribute_lint.span, - lint: attribute_lint.lint_id.lint, - }, - tcx.sess, - Some(tcx), - &attribute_lint.kind, - ); - } - } + rustc_hir_analysis::emit_delayed_lint(lint, tcx); } } } From 22651182ea75830a491c6c631594c1af350b5fd7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Feb 2026 18:54:22 +0100 Subject: [PATCH 6/6] Fix compilation --- compiler/rustc_lint/src/lints.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 03aead778727f..0484550b23936 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1596,7 +1596,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { } } -#[derive(LintDiagnostic)] +#[derive(rustc_macros::LintDiagnostic)] #[diag("{$sort} `{$name}` should have an upper case name")] pub(crate) struct NonUpperCaseGlobal<'a> { pub sort: &'a str,