diff options
| author | bors <bors@rust-lang.org> | 2021-01-17 17:52:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-01-17 17:52:01 +0000 |
| commit | 1f0fc02cc8ab4e0d9dd3e06a6d46fcb72b2a026f (patch) | |
| tree | a90bba13f55c036cc2279b9beac6b30d27a87cfe /compiler | |
| parent | edeb631ad0cd6fdf31e2e31ec90e105d1768be28 (diff) | |
| parent | 13728b8975bf53171cdd94d5edfffb78a2a9179f (diff) | |
| download | rust-1f0fc02cc8ab4e0d9dd3e06a6d46fcb72b2a026f.tar.gz rust-1f0fc02cc8ab4e0d9dd3e06a6d46fcb72b2a026f.zip | |
Auto merge of #80524 - jyn514:unknown-tool-lints, r=flip1995,matthewjasper
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. This may interact with the unstable `tool_lint` feature, which I don't entirely understand, but it will take the burden off those external tools to add their own lint pass, which seems like a step in the right direction to me. - Don't mark `ineffective_unstable_trait_impl` as an internal lint - Use clippy's more advanced lint suggestions - Deprecate the `UNKNOWN_CLIPPY_LINTS` pass (and make it a no-op) - Say 'unknown lint `clippy::x`' instead of 'unknown lint x' This is tested by existing clippy tests. When https://github.com/rust-lang/rust/pull/80527 merges, it will also be tested in rustdoc tests. AFAIK there is no way to test this with rustc directly.
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_lint/src/context.rs | 45 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/levels.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/builtin.rs | 27 |
3 files changed, 60 insertions, 17 deletions
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 0f40324acb1..3971a309982 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -354,10 +354,23 @@ impl LintStore { lint_name.to_string() }; // If the lint was scoped with `tool::` check if the tool lint exists - if tool_name.is_some() { + if let Some(tool_name) = tool_name { match self.by_name.get(&complete_name) { None => match self.lint_groups.get(&*complete_name) { - None => return CheckLintNameResult::Tool(Err((None, String::new()))), + // If the lint isn't registered, there are two possibilities: + None => { + // 1. The tool is currently running, so this lint really doesn't exist. + // FIXME: should this handle tools that never register a lint, like rustfmt? + tracing::debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>()); + let tool_prefix = format!("{}::", tool_name); + return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) { + self.no_lint_suggestion(&complete_name) + } else { + // 2. The tool isn't currently running, so no lints will be registered. + // To avoid giving a false positive, ignore all unknown lints. + CheckLintNameResult::Tool(Err((None, String::new()))) + }; + } Some(LintGroup { lint_ids, .. }) => { return CheckLintNameResult::Tool(Ok(&lint_ids)); } @@ -398,6 +411,21 @@ impl LintStore { } } + fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> { + let name_lower = lint_name.to_lowercase(); + let symbols = + self.get_lints().iter().map(|l| Symbol::intern(&l.name_lower())).collect::<Vec<_>>(); + + if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() { + // First check if the lint name is (partly) in upper case instead of lower case... + CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower))) + } else { + // ...if not, search for lints with a similar name + let suggestion = find_best_match_for_name(&symbols, Symbol::intern(&name_lower), None); + CheckLintNameResult::NoLint(suggestion) + } + } + fn check_tool_name_for_backwards_compat( &self, lint_name: &str, @@ -407,18 +435,7 @@ impl LintStore { match self.by_name.get(&complete_name) { None => match self.lint_groups.get(&*complete_name) { // Now we are sure, that this lint exists nowhere - None => { - let symbols = - self.by_name.keys().map(|name| Symbol::intern(&name)).collect::<Vec<_>>(); - - let suggestion = find_best_match_for_name( - &symbols, - Symbol::intern(&lint_name.to_lowercase()), - None, - ); - - CheckLintNameResult::NoLint(suggestion) - } + None => self.no_lint_suggestion(lint_name), Some(LintGroup { lint_ids, depr, .. }) => { // Reaching this would be weird, but let's cover this case anyway if let Some(LintAlias { name, silent }) = depr { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 37bdc878b16..fc8f84461f9 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -381,6 +381,11 @@ impl<'s> LintLevelsBuilder<'s> { src, Some(li.span().into()), |lint| { + let name = if let Some(tool_name) = tool_name { + format!("{}::{}", tool_name, name) + } else { + name.to_string() + }; let mut db = lint.build(&format!("unknown lint: `{}`", name)); if let Some(suggestion) = suggestion { db.span_suggestion( diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e9632796704..20052ad9bfc 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4,7 +4,7 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use crate::{declare_lint, declare_lint_pass, declare_tool_lint}; +use crate::{declare_lint, declare_lint_pass}; use rustc_span::edition::Edition; use rustc_span::symbol::sym; @@ -2825,8 +2825,29 @@ declare_lint! { }; } -declare_tool_lint! { - pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL, +declare_lint! { + /// The `ineffective_unstable_trait_impl` lint detects `#[unstable]` attributes which are not used. + /// + /// ### Example + /// + /// ```compile_fail + /// #![feature(staged_api)] + /// + /// #[derive(Clone)] + /// #[stable(feature = "x", since = "1")] + /// struct S {} + /// + /// #[unstable(feature = "y", issue = "none")] + /// impl Copy for S {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// `staged_api` does not currently support using a stability attribute on `impl` blocks. + /// `impl`s are always stable if both the type and trait are stable, and always unstable otherwise. + pub INEFFECTIVE_UNSTABLE_TRAIT_IMPL, Deny, "detects `#[unstable]` on stable trait implementations for stable types" } |
