diff options
| author | bors <bors@rust-lang.org> | 2021-07-13 15:06:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-07-13 15:06:10 +0000 |
| commit | 3e1c75c6e25a4db968066bd2ef2dabc7c504d7ca (patch) | |
| tree | 30bfe071b15297a0d7c41b4cd1e2a0c05e07c56c /compiler/rustc_lint/src/internal.rs | |
| parent | ca99e3eb3adf61573b11d859ce2b9ff7db48ccd4 (diff) | |
| parent | 17ebba70d00e94b5136171d3f26d6a0369e7b83c (diff) | |
| download | rust-3e1c75c6e25a4db968066bd2ef2dabc7c504d7ca.tar.gz rust-3e1c75c6e25a4db968066bd2ef2dabc7c504d7ca.zip | |
Auto merge of #86827 - camsteffen:hash-lint-resolved, r=oli-obk
Fix internal `default_hash_types` lint to use resolved path I run into false positives now and then (mostly in Clippy) when I want to name some util after HashMap.
Diffstat (limited to 'compiler/rustc_lint/src/internal.rs')
| -rw-r--r-- | compiler/rustc_lint/src/internal.rs | 79 |
1 files changed, 37 insertions, 42 deletions
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 9b1a339572e..8a4a7089437 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -2,15 +2,17 @@ //! Clippy. use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; -use rustc_ast::{ImplKind, Item, ItemKind}; -use rustc_data_structures::fx::FxHashMap; +use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath, Ty, TyKind}; +use rustc_hir::{ + GenericArg, HirId, Item, ItemKind, MutTy, Mutability, Node, Path, PathSegment, QPath, Ty, + TyKind, +}; use rustc_middle::ty; -use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; declare_tool_lint! { pub rustc::DEFAULT_HASH_TYPES, @@ -19,43 +21,35 @@ declare_tool_lint! { report_in_external_macro: true } -pub struct DefaultHashTypes { - map: FxHashMap<Symbol, Symbol>, -} - -impl DefaultHashTypes { - // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself - #[allow(rustc::default_hash_types)] - pub fn new() -> Self { - let mut map = FxHashMap::default(); - map.insert(sym::HashMap, sym::FxHashMap); - map.insert(sym::HashSet, sym::FxHashSet); - Self { map } - } -} - -impl_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); +declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); -impl EarlyLintPass for DefaultHashTypes { - fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) { - if let Some(replace) = self.map.get(&ident.name) { - cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, |lint| { - // FIXME: We can avoid a copy here. Would require us to take String instead of &str. - let msg = format!("Prefer {} over {}, it has better performance", replace, ident); - lint.build(&msg) - .span_suggestion( - ident.span, - "use", - replace.to_string(), - Applicability::MaybeIncorrect, // FxHashMap, ... needs another import - ) - .note(&format!( - "a `use rustc_data_structures::fx::{}` may be necessary", - replace - )) - .emit(); - }); +impl LateLintPass<'_> for DefaultHashTypes { + fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { + let def_id = match path.res { + Res::Def(rustc_hir::def::DefKind::Struct, id) => id, + _ => return, + }; + if matches!(cx.tcx.hir().get(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) { + // don't lint imports, only actual usages + return; } + let replace = if cx.tcx.is_diagnostic_item(sym::hashmap_type, def_id) { + "FxHashMap" + } else if cx.tcx.is_diagnostic_item(sym::hashset_type, def_id) { + "FxHashSet" + } else { + return; + }; + cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| { + let msg = format!( + "prefer `{}` over `{}`, it has better performance", + replace, + cx.tcx.item_name(def_id) + ); + lint.build(&msg) + .note(&format!("a `use rustc_data_structures::fx::{}` may be necessary", replace)) + .emit(); + }); } } @@ -242,8 +236,9 @@ declare_tool_lint! { declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]); impl EarlyLintPass for LintPassImpl { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Impl(box ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { + if let ast::ItemKind::Impl(box ast::ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind + { if let Some(last) = lint_pass.path.segments.last() { if last.ident.name == sym::LintPass { let expn_data = lint_pass.path.span.ctxt().outer_expn_data(); |
