diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a1c8b8421e7c1..00b335fff3b40 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -88,6 +88,7 @@ use rustc_abi::{CVariadicStatus, ExternAbi}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::lints::DelayedLint; +use rustc_lint::DecorateAttrLint; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{Const, Ty, TyCtxt}; @@ -148,20 +149,17 @@ pub fn provide(providers: &mut Providers) { }; } -fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) { +pub fn emit_delayed_lint(lint: &DelayedLint, tcx: TyCtxt<'_>) { match lint { DelayedLint::AttributeParsing(attribute_lint) => { - tcx.node_span_lint( + tcx.emit_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, - ); + DecorateAttrLint { + sess: tcx.sess, + tcx: Some(tcx), + diagnostic: &attribute_lint.kind, }, ); } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 971170aaba304..5cd5c95f1ec14 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -11,7 +11,7 @@ use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{Diag, Diagnostic, LintBuffer, LintDiagnostic, MultiSpan}; +use rustc_errors::{Diag, Diagnostic, LintBuffer, MultiSpan}; use rustc_feature::Features; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; @@ -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, @@ -546,20 +546,6 @@ pub trait LintContext { self.opt_span_diag_lint(lint, Some(span), decorator); } - /// Emit a lint at `span` from a lazily-constructed lint struct (some type that implements - /// `LintDiagnostic`, typically generated by `#[derive(LintDiagnostic)]`). - fn emit_span_lint_lazy, L: for<'a> LintDiagnostic<'a, ()>>( - &self, - lint: &'static Lint, - span: S, - decorator: impl FnOnce() -> L, - ) { - self.opt_span_lint(lint, Some(span), |lint| { - let decorator = decorator(); - decorator.decorate_lint(lint); - }); - } - /// Emit a lint at the appropriate level, with an associated span. /// /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature @@ -573,16 +559,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); } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 0295df2feca56..a2ee7936685b3 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -15,6 +15,7 @@ use rustc_session::lint::LintPass; use rustc_span::{Ident, Span}; use tracing::debug; +use crate::DecorateBuiltinLint; use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; @@ -36,12 +37,23 @@ 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 { + match diagnostic { DecorateDiagCompat::Builtin(b) => { - diagnostics::decorate_builtin_lint(self.context.sess(), self.tcx, b, diag); + self.context.opt_span_diag_lint( + lint_id.lint, + span, + DecorateBuiltinLint { + sess: self.context.sess(), + tcx: self.tcx, + diagnostic: b, + }, + ); } - 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 31a6351c6e70b..458553fa747ca 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -2,7 +2,8 @@ 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, + Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level, + elided_lifetime_in_path_suggestion, }; use rustc_hir::lints::{AttributeLintKind, FormatWarning}; use rustc_middle::middle::stability; @@ -16,460 +17,487 @@ use crate::lints; mod check_cfg; -pub fn decorate_builtin_lint( - sess: &Session, - tcx: Option>, - diagnostic: BuiltinLintDiag, - diag: &mut Diag<'_, ()>, -) { - match diagnostic { - BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { - let spans: Vec<_> = content - .char_indices() - .filter_map(|(i, c)| { - TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| { - let lo = comment_span.lo() + BytePos(2 + i as u32); - (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) +/// This is a diagnostic struct that will decorate a `BuiltinLintDiag` +/// Directly creating the lint structs is expensive, using this will only decorate the lint structs when needed. +pub struct DecorateBuiltinLint<'sess, 'tcx> { + pub sess: &'sess Session, + pub tcx: Option>, + pub diagnostic: BuiltinLintDiag, +} + +impl<'a> Diagnostic<'a, ()> for DecorateBuiltinLint<'_, '_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + match self.diagnostic { + BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => { + let spans: Vec<_> = content + .char_indices() + .filter_map(|(i, c)| { + TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| { + let lo = comment_span.lo() + BytePos(2 + i as u32); + (c, comment_span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32))) + }) }) - }) - .collect(); - let characters = spans - .iter() - .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: format!("{c:?}") }) - .collect(); - let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion { - spans: spans.iter().map(|(_c, span)| *span).collect(), - }); - - 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) { - Ok(ref s) => { - // FIXME(Manishearth) ideally the emitting code - // can tell us whether or not this is global - let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" }; - - (format!("crate{opt_colon}{s}"), Applicability::MachineApplicable) + .collect(); + let characters = spans + .iter() + .map(|&(c, span)| lints::UnicodeCharNoteSub { span, c_debug: format!("{c:?}") }) + .collect(); + let suggestions = (!spans.is_empty()).then_some(lints::UnicodeTextFlowSuggestion { + spans: spans.iter().map(|(_c, span)| *span).collect(), + }); + + lints::UnicodeTextFlow { + comment_span, + characters, + suggestions, + num_codepoints: spans.len(), } - Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), - }; - lints::AbsPathWithModule { - sugg: lints::AbsPathWithModuleSugg { span: mod_span, applicability, replacement }, + .into_diag(dcx, level) } - .decorate_lint(diag); - } - BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - lints::ElidedLifetimesInPaths { + BuiltinLintDiag::AbsPathWithModule(mod_span) => { + let (replacement, applicability) = + match self.sess.source_map().span_to_snippet(mod_span) { + Ok(ref s) => { + // FIXME(Manishearth) ideally the emitting code + // can tell us whether or not this is global + let opt_colon = + if s.trim_start().starts_with("::") { "" } else { "::" }; + + (format!("crate{opt_colon}{s}"), Applicability::MachineApplicable) + } + Err(_) => ("crate::".to_string(), Applicability::HasPlaceholders), + }; + lints::AbsPathWithModule { + sugg: lints::AbsPathWithModuleSugg { + span: mod_span, + applicability, + replacement, + }, + } + .into_diag(dcx, level) + } + BuiltinLintDiag::ElidedLifetimesInPaths( + n, + path_span, + incl_angl_brckt, + insertion_span, + ) => lints::ElidedLifetimesInPaths { subdiag: elided_lifetime_in_path_suggestion( - sess.source_map(), + self.sess.source_map(), n, path_span, incl_angl_brckt, insertion_span, ), } - .decorate_lint(diag); - } - 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| sess.source_map().guess_head_span(span)); - - lints::UnusedImports { - sugg, + .into_diag(dcx, level), + BuiltinLintDiag::UnusedImports { + remove_whole_use, + num_to_remove, + remove_spans, test_module_span, - num_snippets: span_snippets.len(), - span_snippets: DiagArgValue::StrListSepByAnd( - span_snippets.into_iter().map(Cow::Owned).collect(), - ), + 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) } - .decorate_lint(diag); - } - BuiltinLintDiag::RedundantImport(spans, ident) => { - let subs = spans - .into_iter() - .map(|(span, is_imported)| match (span.is_dummy(), is_imported) { - (false, true) => lints::RedundantImportSub::ImportedHere { span, ident }, - (false, false) => lints::RedundantImportSub::DefinedHere { span, ident }, - (true, true) => lints::RedundantImportSub::ImportedPrelude { span, ident }, - (true, false) => lints::RedundantImportSub::DefinedPrelude { span, ident }, - }) - .collect(); - lints::RedundantImport { subs, ident }.decorate_lint(diag); - } - BuiltinLintDiag::DeprecatedMacro { - suggestion, - suggestion_span, - note, - path, - since_kind, - } => { - let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion { - span: suggestion_span, - kind: "macro".to_owned(), + BuiltinLintDiag::RedundantImport(spans, ident) => { + let subs = spans + .into_iter() + .map(|(span, is_imported)| match (span.is_dummy(), is_imported) { + (false, true) => lints::RedundantImportSub::ImportedHere { span, ident }, + (false, false) => lints::RedundantImportSub::DefinedHere { span, ident }, + (true, true) => lints::RedundantImportSub::ImportedPrelude { span, ident }, + (true, false) => lints::RedundantImportSub::DefinedPrelude { span, ident }, + }) + .collect(); + lints::RedundantImport { subs, ident }.into_diag(dcx, level) + } + BuiltinLintDiag::DeprecatedMacro { suggestion, - }); - - stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind } - .decorate_lint(diag); - } - BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { - let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; - if is_foreign { - lints::PatternsInFnsWithoutBody::Foreign { sub } - } else { - lints::PatternsInFnsWithoutBody::Bodiless { sub } - } - .decorate_lint(diag); - } - BuiltinLintDiag::ReservedPrefix(label_span, prefix) => { - lints::ReservedPrefix { + suggestion_span, + note, + path, + since_kind, + } => { + let sub = suggestion.map(|suggestion| stability::DeprecationSuggestion { + span: suggestion_span, + kind: "macro".to_owned(), + suggestion, + }); + + stability::Deprecated { sub, kind: "macro".to_owned(), path, note, since_kind } + .into_diag(dcx, level) + } + BuiltinLintDiag::PatternsInFnsWithoutBody { span: remove_span, ident, is_foreign } => { + let sub = lints::PatternsInFnsWithoutBodySub { ident, span: remove_span }; + if is_foreign { + lints::PatternsInFnsWithoutBody::Foreign { sub } + } else { + lints::PatternsInFnsWithoutBody::Bodiless { sub } + } + .into_diag(dcx, level) + } + BuiltinLintDiag::ReservedPrefix(label_span, prefix) => 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); - } - BuiltinLintDiag::ReservedString { is_string, suggestion } => { - if is_string { - lints::ReservedString { suggestion }.decorate_lint(diag); - } else { - lints::ReservedMultihash { suggestion }.decorate_lint(diag); + .into_diag(dcx, level), + BuiltinLintDiag::RawPrefix(label_span) => { + lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } + .into_diag(dcx, level) } - } - BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => { - lints::BreakWithLabelAndLoop { + BuiltinLintDiag::ReservedString { is_string, suggestion } => { + if is_string { + lints::ReservedString { suggestion }.into_diag(dcx, level) + } else { + lints::ReservedMultihash { suggestion }.into_diag(dcx, level) + } + } + BuiltinLintDiag::BreakWithLabelAndLoop(sugg_span) => 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 { - Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd { - left: left_sp, - right: right_sp, - sugg, - }, - None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }, - }; - lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag); - } - BuiltinLintDiag::SingleUseLifetime { - param_span, - use_span: Some((use_span, elide)), - deletion_span, - ident, - } => { - debug!(?param_span, ?use_span, ?deletion_span); - let suggestion = if let Some(deletion_span) = deletion_span { - let (use_span, replace_lt) = if elide { - let use_span = sess.source_map().span_extend_while_whitespace(use_span); - (use_span, String::new()) - } else { - (use_span, "'_".to_owned()) - }; - debug!(?deletion_span, ?use_span); - - // issue 107998 for the case such as a wrong function pointer type - // `deletion_span` is empty and there is no need to report lifetime uses here - let deletion_span = - if deletion_span.is_empty() { None } else { Some(deletion_span) }; - Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt }) - } else { - None - }; - - lints::SingleUseLifetime { suggestion, param_span, use_span, ident } - .decorate_lint(diag); - } - BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { - lints::UnusedLifetime { deletion_span, ident }.decorate_lint(diag); - } - BuiltinLintDiag::NamedArgumentUsedPositionally { - position_sp_to_replace, - position_sp_for_msg, - named_arg_sp, - named_arg_name, - is_formatting_arg, - } => { - let (suggestion, name) = if let Some(positional_arg_to_replace) = position_sp_to_replace - { - let mut name = named_arg_name.clone(); - if is_formatting_arg { - name.push('$') + .into_diag(dcx, level), + BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => { + let suggestion = match sugg { + Some((right_sp, sugg)) => lints::DeprecatedWhereClauseLocationSugg::MoveToEnd { + left: left_sp, + right: right_sp, + sugg, + }, + None => lints::DeprecatedWhereClauseLocationSugg::RemoveWhere { span: left_sp }, }; - let span_to_replace = if let Ok(positional_arg_content) = - sess.source_map().span_to_snippet(positional_arg_to_replace) - && positional_arg_content.starts_with(':') - { - positional_arg_to_replace.shrink_to_lo() + lints::DeprecatedWhereClauseLocation { suggestion }.into_diag(dcx, level) + } + BuiltinLintDiag::SingleUseLifetime { + param_span, + use_span: Some((use_span, elide)), + deletion_span, + ident, + } => { + debug!(?param_span, ?use_span, ?deletion_span); + let suggestion = if let Some(deletion_span) = deletion_span { + let (use_span, replace_lt) = if elide { + let use_span = + self.sess.source_map().span_extend_while_whitespace(use_span); + (use_span, String::new()) + } else { + (use_span, "'_".to_owned()) + }; + debug!(?deletion_span, ?use_span); + + // issue 107998 for the case such as a wrong function pointer type + // `deletion_span` is empty and there is no need to report lifetime uses here + let deletion_span = + if deletion_span.is_empty() { None } else { Some(deletion_span) }; + Some(lints::SingleUseLifetimeSugg { deletion_span, use_span, replace_lt }) } else { - positional_arg_to_replace + None }; - (Some(span_to_replace), name) - } else { - (None, String::new()) - }; - lints::NamedArgumentUsedPositionally { + lints::SingleUseLifetime { suggestion, param_span, use_span, ident } + .into_diag(dcx, level) + } + BuiltinLintDiag::SingleUseLifetime { use_span: None, deletion_span, ident, .. } => { + lints::UnusedLifetime { deletion_span, ident }.into_diag(dcx, level) + } + BuiltinLintDiag::NamedArgumentUsedPositionally { + position_sp_to_replace, + position_sp_for_msg, named_arg_sp, - position_label_sp: position_sp_for_msg, - suggestion, - name, named_arg_name, + is_formatting_arg, + } => { + let (suggestion, name) = + if let Some(positional_arg_to_replace) = position_sp_to_replace { + let mut name = named_arg_name.clone(); + if is_formatting_arg { + name.push('$') + }; + let span_to_replace = if let Ok(positional_arg_content) = + self.sess.source_map().span_to_snippet(positional_arg_to_replace) + && positional_arg_content.starts_with(':') + { + positional_arg_to_replace.shrink_to_lo() + } else { + positional_arg_to_replace + }; + (Some(span_to_replace), name) + } else { + (None, String::new()) + }; + + lints::NamedArgumentUsedPositionally { + named_arg_sp, + position_label_sp: position_sp_for_msg, + suggestion, + name, + named_arg_name, + } + .into_diag(dcx, level) } - .decorate_lint(diag); - } - BuiltinLintDiag::AmbiguousGlobReexports { - name, - namespace, - first_reexport_span, - duplicate_reexport_span, - } => { - lints::AmbiguousGlobReexports { + BuiltinLintDiag::AmbiguousGlobReexports { + name, + namespace, + first_reexport_span, + duplicate_reexport_span, + } => lints::AmbiguousGlobReexports { first_reexport: first_reexport_span, duplicate_reexport: duplicate_reexport_span, name, namespace, } - .decorate_lint(diag); - } - BuiltinLintDiag::HiddenGlobReexports { - name, - namespace, - glob_reexport_span, - private_item_span, - } => { - lints::HiddenGlobReexports { + .into_diag(dcx, level), + BuiltinLintDiag::HiddenGlobReexports { + name, + namespace, + glob_reexport_span, + private_item_span, + } => 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); - } - BuiltinLintDiag::AssociatedConstElidedLifetime { - elided, - span: lt_span, - lifetimes_in_scope, - } => { - let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; - let code = if elided { "'static " } else { "'static" }; - lints::AssociatedConstElidedLifetime { - span: lt_span, - code, + .into_diag(dcx, level), + BuiltinLintDiag::UnusedQualifications { removal_span } => { + lints::UnusedQualifications { removal_span }.into_diag(dcx, level) + } + BuiltinLintDiag::AssociatedConstElidedLifetime { elided, + span: lt_span, lifetimes_in_scope, + } => { + let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span }; + let code = if elided { "'static " } else { "'static" }; + lints::AssociatedConstElidedLifetime { + span: lt_span, + code, + elided, + lifetimes_in_scope, + } + .into_diag(dcx, level) } - .decorate_lint(diag); - } - BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span { - Some(wildcard_span) => { - lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span } - .decorate_lint(diag) - } - None => lints::UnreachableCfgSelectPredicate { span }.decorate_lint(diag), - }, + BuiltinLintDiag::UnreachableCfg { span, wildcard_span } => match wildcard_span { + Some(wildcard_span) => { + lints::UnreachableCfgSelectPredicateWildcard { span, wildcard_span } + .into_diag(dcx, level) + } + None => lints::UnreachableCfgSelectPredicate { span }.into_diag(dcx, level), + }, - BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { - lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) - } - BuiltinLintDiag::UnusedVisibility(span) => { - lints::UnusedVisibility { span }.decorate_lint(diag) + BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { + lints::UnusedCrateDependency { extern_crate, local_crate }.into_diag(dcx, level) + } + BuiltinLintDiag::UnusedVisibility(span) => { + lints::UnusedVisibility { span }.into_diag(dcx, level) + } + BuiltinLintDiag::AttributeLint(kind) => { + DecorateAttrLint { sess: self.sess, tcx: self.tcx, diagnostic: &kind } + .into_diag(dcx, level) + } } - BuiltinLintDiag::AttributeLint(kind) => decorate_attribute_lint(sess, tcx, &kind, diag), } } -pub fn decorate_attribute_lint( - sess: &Session, - tcx: Option>, - kind: &AttributeLintKind, - diag: &mut Diag<'_, ()>, -) { - match kind { - &AttributeLintKind::UnusedDuplicate { this, other, warning } => { - lints::UnusedDuplicate { this, other, warning }.decorate_lint(diag) - } - AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => { - 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(""), +/// This is a diagnostic struct that will decorate a `AttributeLintKind` +/// Directly creating the lint structs is expensive, using this will only decorate the lint structs when needed. +pub struct DecorateAttrLint<'a, 'sess, 'tcx> { + pub sess: &'sess Session, + pub tcx: Option>, + pub diagnostic: &'a AttributeLintKind, +} + +impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + match self.diagnostic { + &AttributeLintKind::UnusedDuplicate { this, other, warning } => { + lints::UnusedDuplicate { this, other, warning }.into_diag(dcx, level) } - .decorate_lint(diag) - } - AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => { - lints::EmptyAttributeList { - attr_span: *first_span, - attr_path: attr_path.clone(), - valid_without_list: *valid_without_list, + AttributeLintKind::IllFormedAttributeInput { suggestions, docs } => { + 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(""), + } + .into_diag(dcx, level) } - .decorate_lint(diag) - } - AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => { - lints::InvalidTargetLint { - name: name.clone(), - target, - applied: DiagArgValue::StrListSepByAnd( - applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(), - ), - only, - attr_span: *attr_span, + AttributeLintKind::EmptyAttribute { first_span, attr_path, valid_without_list } => { + lints::EmptyAttributeList { + attr_span: *first_span, + attr_path: attr_path.clone(), + valid_without_list: *valid_without_list, + } + .into_diag(dcx, level) } - .decorate_lint(diag) - } - &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => { - lints::InvalidAttrStyle { + AttributeLintKind::InvalidTarget { name, target, applied, only, attr_span } => { + lints::InvalidTargetLint { + name: name.clone(), + target, + applied: DiagArgValue::StrListSepByAnd( + applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(), + ), + only, + attr_span: *attr_span, + } + .into_diag(dcx, level) + } + &AttributeLintKind::InvalidStyle { + ref name, + is_used_as_inner, + target, + target_span, + } => 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 { - span: attribute_name_span, - suggestion: sugg_spans - .map(|(left, right)| lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }), + .into_diag(dcx, level), + &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => { + lints::UnsafeAttrOutsideUnsafeLint { + span: attribute_name_span, + suggestion: sugg_spans.map(|(left, right)| { + lints::UnsafeAttrOutsideUnsafeSuggestion { left, right } + }), + } + .into_diag(dcx, level) + } + &AttributeLintKind::UnexpectedCfgName(name, value) => { + check_cfg::unexpected_cfg_name(self.sess, self.tcx, name, value) + .into_diag(dcx, level) + } + &AttributeLintKind::UnexpectedCfgValue(name, value) => { + check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value) + .into_diag(dcx, level) + } + &AttributeLintKind::DuplicateDocAlias { first_definition } => { + lints::DocAliasDuplicated { first_defn: first_definition }.into_diag(dcx, level) } - .decorate_lint(diag) - } - &AttributeLintKind::UnexpectedCfgName(name, value) => { - check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag) - } - &AttributeLintKind::UnexpectedCfgValue(name, value) => { - check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag) - } - &AttributeLintKind::DuplicateDocAlias { first_definition } => { - lints::DocAliasDuplicated { first_defn: first_definition }.decorate_lint(diag) - } - &AttributeLintKind::DocAutoCfgExpectsHideOrShow => { - lints::DocAutoCfgExpectsHideOrShow.decorate_lint(diag) - } + &AttributeLintKind::DocAutoCfgExpectsHideOrShow => { + lints::DocAutoCfgExpectsHideOrShow.into_diag(dcx, level) + } - &AttributeLintKind::AmbiguousDeriveHelpers => { - lints::AmbiguousDeriveHelpers.decorate_lint(diag) - } + &AttributeLintKind::AmbiguousDeriveHelpers => { + lints::AmbiguousDeriveHelpers.into_diag(dcx, level) + } - &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => { - lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.decorate_lint(diag) - } + &AttributeLintKind::DocAutoCfgHideShowUnexpectedItem { attr_name } => { + lints::DocAutoCfgHideShowUnexpectedItem { attr_name }.into_diag(dcx, level) + } - &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => { - lints::DocAutoCfgHideShowExpectsList { attr_name }.decorate_lint(diag) - } + &AttributeLintKind::DocAutoCfgHideShowExpectsList { attr_name } => { + lints::DocAutoCfgHideShowExpectsList { attr_name }.into_diag(dcx, level) + } - &AttributeLintKind::DocInvalid => { lints::DocInvalid }.decorate_lint(diag), + &AttributeLintKind::DocInvalid => lints::DocInvalid.into_diag(dcx, level), - &AttributeLintKind::DocUnknownInclude { span, inner, value } => { - lints::DocUnknownInclude { inner, value, sugg: (span, Applicability::MaybeIncorrect) } - } - .decorate_lint(diag), + &AttributeLintKind::DocUnknownInclude { span, inner, value } => { + lints::DocUnknownInclude { + inner, + value, + sugg: (span, Applicability::MaybeIncorrect), + } + .into_diag(dcx, level) + } - &AttributeLintKind::DocUnknownSpotlight { span } => { - lints::DocUnknownSpotlight { sugg_span: span }.decorate_lint(diag) - } + &AttributeLintKind::DocUnknownSpotlight { span } => { + lints::DocUnknownSpotlight { sugg_span: span }.into_diag(dcx, level) + } - &AttributeLintKind::DocUnknownPasses { name, span } => { - lints::DocUnknownPasses { name, note_span: span }.decorate_lint(diag) - } + &AttributeLintKind::DocUnknownPasses { name, span } => { + lints::DocUnknownPasses { name, note_span: span }.into_diag(dcx, level) + } - &AttributeLintKind::DocUnknownPlugins { span } => { - lints::DocUnknownPlugins { label_span: span }.decorate_lint(diag) - } + &AttributeLintKind::DocUnknownPlugins { span } => { + lints::DocUnknownPlugins { label_span: span }.into_diag(dcx, level) + } - &AttributeLintKind::DocUnknownAny { name } => { - lints::DocUnknownAny { name }.decorate_lint(diag) - } + &AttributeLintKind::DocUnknownAny { name } => { + lints::DocUnknownAny { name }.into_diag(dcx, level) + } - &AttributeLintKind::DocAutoCfgWrongLiteral => { - lints::DocAutoCfgWrongLiteral.decorate_lint(diag) - } + &AttributeLintKind::DocAutoCfgWrongLiteral => { + lints::DocAutoCfgWrongLiteral.into_diag(dcx, level) + } - &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.decorate_lint(diag), + &AttributeLintKind::DocTestTakesList => lints::DocTestTakesList.into_diag(dcx, level), - &AttributeLintKind::DocTestUnknown { name } => { - lints::DocTestUnknown { name }.decorate_lint(diag) - } + &AttributeLintKind::DocTestUnknown { name } => { + lints::DocTestUnknown { name }.into_diag(dcx, level) + } - &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.decorate_lint(diag), + &AttributeLintKind::DocTestLiteral => lints::DocTestLiteral.into_diag(dcx, level), - &AttributeLintKind::AttrCrateLevelOnly => lints::AttrCrateLevelOnly.decorate_lint(diag), + &AttributeLintKind::AttrCrateLevelOnly => { + lints::AttrCrateLevelOnly.into_diag(dcx, level) + } - &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => { - lints::DoNotRecommendDoesNotExpectArgs.decorate_lint(diag) - } + &AttributeLintKind::DoNotRecommendDoesNotExpectArgs => { + lints::DoNotRecommendDoesNotExpectArgs.into_diag(dcx, level) + } - &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes { - sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), - } - .decorate_lint(diag), + &AttributeLintKind::CrateTypeUnknown { span, suggested } => lints::UnknownCrateTypes { + sugg: suggested.map(|s| lints::UnknownCrateTypesSuggestion { span, snippet: s }), + } + .into_diag(dcx, level), - &AttributeLintKind::MalformedDoc => lints::MalformedDoc.decorate_lint(diag), + &AttributeLintKind::MalformedDoc => lints::MalformedDoc.into_diag(dcx, level), - &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.decorate_lint(diag), + &AttributeLintKind::ExpectedNoArgs => lints::ExpectedNoArgs.into_diag(dcx, level), - &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.decorate_lint(diag), - &AttributeLintKind::MalformedOnUnimplementedAttr { span } => { - lints::MalformedOnUnimplementedAttrLint { span }.decorate_lint(diag) - } - &AttributeLintKind::MalformedOnConstAttr { span } => { - lints::MalformedOnConstAttrLint { span }.decorate_lint(diag) - } - AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning { - FormatWarning::PositionalArgument { .. } => { - lints::DisallowedPositionalArgument.decorate_lint(diag) + &AttributeLintKind::ExpectedNameValue => lints::ExpectedNameValue.into_diag(dcx, level), + &AttributeLintKind::MalformedOnUnimplementedAttr { span } => { + lints::MalformedOnUnimplementedAttrLint { span }.into_diag(dcx, level) } - FormatWarning::InvalidSpecifier { .. } => { - lints::InvalidFormatSpecifier.decorate_lint(diag) + &AttributeLintKind::MalformedOnConstAttr { span } => { + lints::MalformedOnConstAttrLint { span }.into_diag(dcx, level) + } + AttributeLintKind::MalformedDiagnosticFormat { warning } => match warning { + FormatWarning::PositionalArgument { .. } => { + lints::DisallowedPositionalArgument.into_diag(dcx, level) + } + FormatWarning::InvalidSpecifier { .. } => { + lints::InvalidFormatSpecifier.into_diag(dcx, level) + } + }, + AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => { + lints::WrappedParserError { description, label, span: *span }.into_diag(dcx, level) + } + &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => { + lints::IgnoredDiagnosticOption { option_name, first_span, later_span } + .into_diag(dcx, level) + } + &AttributeLintKind::MissingOptionsForOnUnimplemented => { + lints::MissingOptionsForOnUnimplementedAttr.into_diag(dcx, level) + } + &AttributeLintKind::MissingOptionsForOnConst => { + lints::MissingOptionsForOnConstAttr.into_diag(dcx, level) } - }, - AttributeLintKind::DiagnosticWrappedParserError { description, label, span } => { - lints::WrappedParserError { description, label, span: *span }.decorate_lint(diag) - } - &AttributeLintKind::IgnoredDiagnosticOption { option_name, first_span, later_span } => { - lints::IgnoredDiagnosticOption { option_name, first_span, later_span } - .decorate_lint(diag) - } - &AttributeLintKind::MissingOptionsForOnUnimplemented => { - lints::MissingOptionsForOnUnimplementedAttr.decorate_lint(diag) - } - &AttributeLintKind::MissingOptionsForOnConst => { - lints::MissingOptionsForOnConstAttr.decorate_lint(diag) } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 34276eb76cf39..194a8cfc2ea3d 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -131,7 +131,7 @@ use unused::*; #[rustfmt::skip] 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::diagnostics::{DecorateAttrLint, DecorateBuiltinLint}; pub use early::{EarlyCheckNode, check_ast_node}; pub use late::{check_crate, late_lint_mod, unerased_lint_store}; pub use levels::LintLevelsBuilder; diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index bd7ce30e2ccad..40021debca0b4 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; @@ -1600,7 +1600,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("{$sort} `{$name}` should have an upper case name")] pub(crate) struct NonUpperCaseGlobal<'a> { pub sort: &'a str, @@ -2712,7 +2712,7 @@ pub(crate) struct UnexpectedCfgCargoMacroHelp { pub crate_name: Symbol, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unexpected `cfg` condition name: `{$name}`")] pub(crate) struct UnexpectedCfgName { #[subdiagnostic] @@ -2859,7 +2859,7 @@ pub(crate) mod unexpected_cfg_name { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag( "unexpected `cfg` condition value: {$has_value -> [true] `{$value}` @@ -2994,7 +2994,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 { @@ -3003,7 +3003,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} @@ -3018,7 +3018,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" @@ -3058,7 +3058,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" )] @@ -3077,14 +3077,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} @@ -3128,7 +3128,7 @@ pub(crate) enum UnusedImportsSugg { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("the item `{$ident}` is imported redundantly")] pub(crate) struct RedundantImport { #[subdiagnostic] @@ -3164,7 +3164,7 @@ pub(crate) enum RedundantImportSub { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] pub(crate) enum PatternsInFnsWithoutBody { #[diag("patterns aren't allowed in foreign function declarations")] Foreign { @@ -3191,7 +3191,7 @@ pub(crate) struct PatternsInFnsWithoutBodySub { pub ident: Ident, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("prefix `{$prefix}` is unknown")] pub(crate) struct ReservedPrefix { #[label("unknown prefix")] @@ -3206,7 +3206,7 @@ pub(crate) struct ReservedPrefix { pub prefix: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("prefix `'r` is reserved")] pub(crate) struct RawPrefix { #[label("reserved prefix")] @@ -3219,7 +3219,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" )] @@ -3237,7 +3237,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 { @@ -3266,7 +3266,7 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg { }, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("lifetime parameter `{$ident}` only used once")] pub(crate) struct SingleUseLifetime { #[label("this lifetime...")] @@ -3290,7 +3290,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")] @@ -3299,7 +3299,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")] @@ -3318,7 +3318,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")] @@ -3330,7 +3330,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( @@ -3344,7 +3344,7 @@ pub(crate) struct HiddenGlobReexports { pub namespace: String, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unnecessary qualification")] pub(crate) struct UnusedQualifications { #[suggestion( @@ -3356,7 +3356,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 @@ -3422,7 +3422,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( @@ -3433,7 +3433,7 @@ pub(crate) struct ReservedString { pub suggestion: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("reserved token in Rust 2024")] pub(crate) struct ReservedMultihash { #[suggestion( @@ -3642,7 +3642,7 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag("unused attribute")] #[note( "{$valid_without_list -> @@ -3664,7 +3664,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!" @@ -3684,7 +3684,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}]` @@ -3699,7 +3699,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")] @@ -3712,28 +3712,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")] @@ -3751,7 +3751,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 { @@ -3764,38 +3764,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, @@ -3807,7 +3807,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")] @@ -3821,7 +3821,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 " @@ -3833,7 +3833,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 " @@ -3844,42 +3844,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] @@ -3894,14 +3894,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")] @@ -3911,19 +3911,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, @@ -3932,7 +3932,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, @@ -3942,17 +3942,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 { @@ -3960,7 +3960,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 { diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index d7db55b58d00f..b42966ce8ec8e 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,6 +1,6 @@ use rustc_abi::ExternAbi; use rustc_attr_parsing::AttributeParser; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level}; use rustc_hir::attrs::{AttributeKind, ReprAttr}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -461,6 +461,19 @@ declare_lint! { declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]); +struct NonUpperCaseGlobalGenerator<'a, F: FnOnce() -> NonUpperCaseGlobal<'a>> { + callback: F, +} + +impl<'a, 'b, F: FnOnce() -> NonUpperCaseGlobal<'b>> Diagnostic<'a, ()> + for NonUpperCaseGlobalGenerator<'b, F> +{ + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let Self { callback } = self; + callback().into_diag(dcx, level) + } +} + impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext<'_>, sort: &str, did: Option, ident: &Ident) { let name = ident.name.as_str(); @@ -517,7 +530,7 @@ impl NonUpperCaseGlobals { } } - cx.emit_span_lint_lazy(NON_UPPER_CASE_GLOBALS, ident.span, || { + let callback = || { // Compute usages lazily as it can expansive and useless when the lint is allowed. // cf. https://github.com/rust-lang/rust/pull/142645#issuecomment-2993024625 let usages = if can_change_usages @@ -537,7 +550,12 @@ impl NonUpperCaseGlobals { }; NonUpperCaseGlobal { sort, name, sub, usages } - }); + }; + cx.emit_span_lint( + NON_UPPER_CASE_GLOBALS, + ident.span, + NonUpperCaseGlobalGenerator { callback }, + ); } } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 541ab3d1c295e..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}; @@ -910,23 +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) => { - 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_hir_analysis::emit_delayed_lint(lint, tcx); } } } 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 |