Rollup merge of #115152 - weihanglo:lint-refactor, r=compiler-errors

refactor(lint): translate `RenamedOrRemovedLint`

I was trying to address <https://github.com/rust-lang/cargo/issues/12495> and found that maybe I should refactor relevant lints a bit.

This PR translates `RenamedOrRemovedLint` into fluent file. To make diagnostic types clearer and easier to organize, this PR splits it into two structs.

The second commit adds lifetime annotations for removing unnecessary clones. If people feel too noisy, we can revert such change.

### Possibly relevant UI tests:

* `tests/ui/lint-removed*`
* `tests/ui/lint-renamed*`
* `tests/ui/rustdoc-renamed.rs`
* `tests/rustdoc-ui/lints/unknown-renamed-lints.rs`
This commit is contained in:
Weihang Lo 2023-08-24 22:53:59 +01:00 committed by GitHub
commit 1d526692d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 54 deletions

View File

@ -158,13 +158,15 @@ lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
lint_check_name_removed = lint `{$lint_name}` has been removed: {$reason}
lint_check_name_renamed = lint `{$lint_name}` has been renamed to `{$replace}`
lint_check_name_unknown = unknown lint: `{$lint_name}`
.help = did you mean: `{$suggestion}`
lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
lint_check_name_warning = {$msg}
lint_command_line_source = `forbid` lint level was set on command line
lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike
@ -484,8 +486,11 @@ lint_redundant_semicolons =
*[false] this semicolon
}
lint_renamed_or_removed_lint = {$msg}
lint_removed_lint = lint `{$name}` has been removed: {$reason}
lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}`
.suggestion = use the new name
.help = use the new name `{$replace}`
lint_requested_level = requested on the command line with `{$level} {$lint_name}`

View File

@ -17,8 +17,8 @@
use self::TargetLint::*;
use crate::errors::{
CheckNameDeprecated, CheckNameUnknown, CheckNameUnknownTool, CheckNameWarning, RequestedLevel,
UnsupportedGroup,
CheckNameDeprecated, CheckNameRemoved, CheckNameRenamed, CheckNameUnknown,
CheckNameUnknownTool, RequestedLevel, UnsupportedGroup,
};
use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
@ -124,9 +124,10 @@ pub enum CheckLintNameResult<'a> {
NoLint(Option<Symbol>),
/// The lint refers to a tool that has not been registered.
NoTool,
/// The lint is either renamed or removed. This is the warning
/// message, and an optional new name (`None` if removed).
Warning(String, Option<String>),
/// The lint has been renamed to a new name.
Renamed(String),
/// The lint has been removed due to the given reason.
Removed(String),
/// The lint is from a tool. If the Option is None, then either
/// the lint does not exist in the tool or the code was not
/// compiled with the tool and therefore the lint was never
@ -342,25 +343,32 @@ impl LintStore {
sess.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
return;
}
let lint_name = lint_name.to_string();
match self.check_lint_name(lint_name_only, tool_name, registered_tools) {
CheckLintNameResult::Warning(msg, _) => {
sess.emit_warning(CheckNameWarning {
msg,
CheckLintNameResult::Renamed(replace) => {
sess.emit_warning(CheckNameRenamed {
lint_name,
replace: &replace,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::Removed(reason) => {
sess.emit_warning(CheckNameRemoved {
lint_name,
reason: &reason,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::NoLint(suggestion) => {
sess.emit_err(CheckNameUnknown {
lint_name: lint_name.clone(),
lint_name,
suggestion,
sub: RequestedLevel { level, lint_name },
});
}
CheckLintNameResult::Tool(Err((Some(_), new_name))) => {
sess.emit_warning(CheckNameDeprecated {
lint_name: lint_name.clone(),
new_name,
lint_name,
new_name: &new_name,
sub: RequestedLevel { level, lint_name },
});
}
@ -445,14 +453,8 @@ impl LintStore {
}
}
match self.by_name.get(&complete_name) {
Some(Renamed(new_name, _)) => CheckLintNameResult::Warning(
format!("lint `{complete_name}` has been renamed to `{new_name}`"),
Some(new_name.to_owned()),
),
Some(Removed(reason)) => CheckLintNameResult::Warning(
format!("lint `{complete_name}` has been removed: {reason}"),
None,
),
Some(Renamed(new_name, _)) => CheckLintNameResult::Renamed(new_name.to_string()),
Some(Removed(reason)) => CheckLintNameResult::Removed(reason.to_string()),
None => match self.lint_groups.get(&*complete_name) {
// If neither the lint, nor the lint group exists check if there is a `clippy::`
// variant of this lint

View File

@ -91,9 +91,9 @@ pub struct BuiltinEllipsisInclusiveRangePatterns {
#[derive(Subdiagnostic)]
#[note(lint_requested_level)]
pub struct RequestedLevel {
pub struct RequestedLevel<'a> {
pub level: Level,
pub lint_name: String,
pub lint_name: &'a str,
}
#[derive(Diagnostic)]
@ -102,13 +102,13 @@ pub struct UnsupportedGroup {
pub lint_group: String,
}
pub struct CheckNameUnknown {
pub lint_name: String,
pub struct CheckNameUnknown<'a> {
pub lint_name: &'a str,
pub suggestion: Option<Symbol>,
pub sub: RequestedLevel,
pub sub: RequestedLevel<'a>,
}
impl IntoDiagnostic<'_> for CheckNameUnknown {
impl IntoDiagnostic<'_> for CheckNameUnknown<'_> {
fn into_diagnostic(
self,
handler: &Handler,
@ -127,25 +127,35 @@ impl IntoDiagnostic<'_> for CheckNameUnknown {
#[derive(Diagnostic)]
#[diag(lint_check_name_unknown_tool, code = "E0602")]
pub struct CheckNameUnknownTool {
pub struct CheckNameUnknownTool<'a> {
pub tool_name: Symbol,
#[subdiagnostic]
pub sub: RequestedLevel,
pub sub: RequestedLevel<'a>,
}
#[derive(Diagnostic)]
#[diag(lint_check_name_warning)]
pub struct CheckNameWarning {
pub msg: String,
#[diag(lint_check_name_renamed)]
pub struct CheckNameRenamed<'a> {
pub lint_name: &'a str,
pub replace: &'a str,
#[subdiagnostic]
pub sub: RequestedLevel,
pub sub: RequestedLevel<'a>,
}
#[derive(Diagnostic)]
#[diag(lint_check_name_removed)]
pub struct CheckNameRemoved<'a> {
pub lint_name: &'a str,
pub reason: &'a str,
#[subdiagnostic]
pub sub: RequestedLevel<'a>,
}
#[derive(Diagnostic)]
#[diag(lint_check_name_deprecated)]
pub struct CheckNameDeprecated {
pub lint_name: String,
pub new_name: String,
pub struct CheckNameDeprecated<'a> {
pub lint_name: &'a str,
pub new_name: &'a str,
#[subdiagnostic]
pub sub: RequestedLevel,
pub sub: RequestedLevel<'a>,
}

View File

@ -4,8 +4,8 @@ use crate::{
fluent_generated as fluent,
late::unerased_lint_store,
lints::{
DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint,
RenamedOrRemovedLint, RenamedOrRemovedLintSuggestion, UnknownLint, UnknownLintSuggestion,
DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, RemovedLint,
RenamedLint, RenamedLintSuggestion, UnknownLint, UnknownLintSuggestion,
},
};
use rustc_ast as ast;
@ -915,18 +915,26 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
_ if !self.warn_about_weird_lints => {}
CheckLintNameResult::Warning(msg, renamed) => {
CheckLintNameResult::Renamed(new_name) => {
let suggestion =
renamed.as_ref().map(|replace| RenamedOrRemovedLintSuggestion {
suggestion: sp,
replace: replace.as_str(),
});
RenamedLintSuggestion { suggestion: sp, replace: new_name.as_str() };
let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
self.emit_spanned_lint(
RENAMED_AND_REMOVED_LINTS,
sp.into(),
RenamedOrRemovedLint { msg, suggestion },
RenamedLint { name: name.as_str(), suggestion },
);
}
CheckLintNameResult::Removed(reason) => {
let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
self.emit_spanned_lint(
RENAMED_AND_REMOVED_LINTS,
sp.into(),
RemovedLint { name: name.as_str(), reason: reason.as_str() },
);
}
CheckLintNameResult::NoLint(suggestion) => {
let name = if let Some(tool_ident) = tool_ident {
format!("{}::{}", tool_ident.name, name)
@ -945,7 +953,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
// If this lint was renamed, apply the new lint instead of ignoring the attribute.
// This happens outside of the match because the new lint should be applied even if
// we don't warn about the name change.
if let CheckLintNameResult::Warning(_, Some(new_name)) = lint_result {
if let CheckLintNameResult::Renamed(new_name) = lint_result {
// Ignore any errors or warnings that happen because the new name is inaccurate
// NOTE: `new_name` already includes the tool name, so we don't have to add it again.
if let CheckLintNameResult::Ok(ids) =

View File

@ -1012,23 +1012,29 @@ pub struct DeprecatedLintName<'a> {
pub replace: &'a str,
}
// FIXME: Non-translatable msg
#[derive(LintDiagnostic)]
#[diag(lint_renamed_or_removed_lint)]
pub struct RenamedOrRemovedLint<'a> {
pub msg: &'a str,
#[diag(lint_renamed_lint)]
pub struct RenamedLint<'a> {
pub name: &'a str,
#[subdiagnostic]
pub suggestion: Option<RenamedOrRemovedLintSuggestion<'a>>,
pub suggestion: RenamedLintSuggestion<'a>,
}
#[derive(Subdiagnostic)]
#[suggestion(lint_suggestion, code = "{replace}", applicability = "machine-applicable")]
pub struct RenamedOrRemovedLintSuggestion<'a> {
pub struct RenamedLintSuggestion<'a> {
#[primary_span]
pub suggestion: Span,
pub replace: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(lint_removed_lint)]
pub struct RemovedLint<'a> {
pub name: &'a str,
pub reason: &'a str,
}
#[derive(LintDiagnostic)]
#[diag(lint_unknown_lint)]
pub struct UnknownLint {