Skip to content

Commit 5053db7

Browse files
committed
Don't make tools responsible for checking unknown and renamed lints
Previously, clippy (and any other tool emitting lints) had to have their own separate UNKNOWN_LINTS pass, because the compiler assumed any tool lint could be valid. Now, as long as any lint starting with the tool prefix exists, the compiler will warn when an unknown lint is present.
1 parent e48eb37 commit 5053db7

File tree

2 files changed

+30
-14
lines changed

2 files changed

+30
-14
lines changed

compiler/rustc_lint/src/context.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,23 @@ impl LintStore {
354354
lint_name.to_string()
355355
};
356356
// If the lint was scoped with `tool::` check if the tool lint exists
357-
if tool_name.is_some() {
357+
if let Some(tool_name) = tool_name {
358358
match self.by_name.get(&complete_name) {
359359
None => match self.lint_groups.get(&*complete_name) {
360-
None => return CheckLintNameResult::Tool(Err((None, String::new()))),
360+
// If the lint isn't registered, there are two possibilities:
361+
None => {
362+
// 1. The tool is currently running, so this lint really doesn't exist.
363+
// FIXME: should this handle tools that never register a lint, like rustfmt?
364+
tracing::debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
365+
let tool_prefix = format!("{}::", tool_name);
366+
return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
367+
self.no_lint_suggestion(&complete_name)
368+
} else {
369+
// 2. The tool isn't currently running, so no lints will be registered.
370+
// To avoid giving a false positive, ignore all unknown lints.
371+
CheckLintNameResult::Tool(Err((None, String::new())))
372+
};
373+
}
361374
Some(LintGroup { lint_ids, .. }) => {
362375
return CheckLintNameResult::Tool(Ok(&lint_ids));
363376
}
@@ -398,6 +411,15 @@ impl LintStore {
398411
}
399412
}
400413

414+
fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> {
415+
let symbols = self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>();
416+
417+
let suggestion =
418+
find_best_match_for_name(&symbols, Symbol::intern(&lint_name.to_lowercase()), None);
419+
420+
CheckLintNameResult::NoLint(suggestion)
421+
}
422+
401423
fn check_tool_name_for_backwards_compat(
402424
&self,
403425
lint_name: &str,
@@ -407,18 +429,7 @@ impl LintStore {
407429
match self.by_name.get(&complete_name) {
408430
None => match self.lint_groups.get(&*complete_name) {
409431
// Now we are sure, that this lint exists nowhere
410-
None => {
411-
let symbols =
412-
self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>();
413-
414-
let suggestion = find_best_match_for_name(
415-
&symbols,
416-
Symbol::intern(&lint_name.to_lowercase()),
417-
None,
418-
);
419-
420-
CheckLintNameResult::NoLint(suggestion)
421-
}
432+
None => self.no_lint_suggestion(lint_name),
422433
Some(LintGroup { lint_ids, depr, .. }) => {
423434
// Reaching this would be weird, but let's cover this case anyway
424435
if let Some(LintAlias { name, silent }) = depr {

compiler/rustc_lint/src/levels.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,11 @@ impl<'s> LintLevelsBuilder<'s> {
381381
src,
382382
Some(li.span().into()),
383383
|lint| {
384+
let name = if let Some(tool_name) = tool_name {
385+
format!("{}::{}", tool_name, name)
386+
} else {
387+
name.to_string()
388+
};
384389
let mut db = lint.build(&format!("unknown lint: `{}`", name));
385390
if let Some(suggestion) = suggestion {
386391
db.span_suggestion(

0 commit comments

Comments
 (0)