diff options
| author | surechen <chenshuo17@huawei.com> | 2023-11-10 10:11:24 +0800 |
|---|---|---|
| committer | surechen <chenshuo17@huawei.com> | 2024-02-18 16:38:11 +0800 |
| commit | a61126cef6c4083d57e22835033eb2eefdd31bac (patch) | |
| tree | 8816d1d780e97b77f943c48de09ee330fee3ac9d /compiler/rustc_resolve/src/check_unused.rs | |
| parent | d3df8ff85121146f2ac5e863e0c9eaba4bf35d32 (diff) | |
| download | rust-a61126cef6c4083d57e22835033eb2eefdd31bac.tar.gz rust-a61126cef6c4083d57e22835033eb2eefdd31bac.zip | |
By tracking import use types to check whether it is scope uses or the other situations like module-relative uses, we can do more accurate redundant import checking.
fixes #117448 For example unnecessary imports in std::prelude that can be eliminated: ```rust use std::option::Option::Some;//~ WARNING the item `Some` is imported redundantly use std::option::Option::None; //~ WARNING the item `None` is imported redundantly ```
Diffstat (limited to 'compiler/rustc_resolve/src/check_unused.rs')
| -rw-r--r-- | compiler/rustc_resolve/src/check_unused.rs | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index c14788b841d..37cc50f6943 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -27,9 +27,10 @@ use crate::imports::ImportKind; use crate::module_to_string; use crate::Resolver; +use crate::NameBindingKind; use rustc_ast as ast; use rustc_ast::visit::{self, Visitor}; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{pluralize, MultiSpan}; use rustc_hir::def::{DefKind, Res}; @@ -38,14 +39,14 @@ use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, DUMMY_SP}; -struct UnusedImport<'a> { - use_tree: &'a ast::UseTree, +struct UnusedImport { + use_tree: ast::UseTree, use_tree_id: ast::NodeId, item_span: Span, unused: UnordSet<ast::NodeId>, } -impl<'a> UnusedImport<'a> { +impl UnusedImport { fn add(&mut self, id: ast::NodeId) { self.unused.insert(id); } @@ -54,7 +55,7 @@ impl<'a> UnusedImport<'a> { struct UnusedImportCheckVisitor<'a, 'b, 'tcx> { r: &'a mut Resolver<'b, 'tcx>, /// All the (so far) unused imports, grouped path list - unused_imports: FxIndexMap<ast::NodeId, UnusedImport<'a>>, + unused_imports: FxIndexMap<ast::NodeId, UnusedImport>, extern_crate_items: Vec<ExternCrateToLint>, base_use_tree: Option<&'a ast::UseTree>, base_id: ast::NodeId, @@ -100,9 +101,9 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { } } - fn unused_import(&mut self, id: ast::NodeId) -> &mut UnusedImport<'a> { + fn unused_import(&mut self, id: ast::NodeId) -> &mut UnusedImport { let use_tree_id = self.base_id; - let use_tree = self.base_use_tree.unwrap(); + let use_tree = self.base_use_tree.unwrap().clone(); let item_span = self.item_span; self.unused_imports.entry(id).or_insert_with(|| UnusedImport { @@ -197,7 +198,7 @@ enum UnusedSpanResult { } fn calc_unused_spans( - unused_import: &UnusedImport<'_>, + unused_import: &UnusedImport, use_tree: &ast::UseTree, use_tree_id: ast::NodeId, ) -> UnusedSpanResult { @@ -287,7 +288,7 @@ impl Resolver<'_, '_> { for import in self.potentially_unused_imports.iter() { match import.kind { - _ if import.used.get() + _ if import.used.get().is_some() || import.expect_vis().is_public() || import.span.is_dummy() => { @@ -336,7 +337,7 @@ impl Resolver<'_, '_> { for unused in visitor.unused_imports.values() { let mut fixes = Vec::new(); - let spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) { + let spans = match calc_unused_spans(unused, &unused.use_tree, unused.use_tree_id) { UnusedSpanResult::Used => continue, UnusedSpanResult::FlatUnused(span, remove) => { fixes.push((remove, String::new())); @@ -483,5 +484,30 @@ impl Resolver<'_, '_> { BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span }, ); } + + let unused_imports = visitor.unused_imports; + let mut check_redundant_imports = FxIndexSet::default(); + for module in self.arenas.local_modules().iter() { + for (_key, resolution) in self.resolutions(*module).borrow().iter() { + let resolution = resolution.borrow(); + + if let Some(binding) = resolution.binding + && let NameBindingKind::Import { import, .. } = binding.kind + && let ImportKind::Single { id, .. } = import.kind + { + if let Some(unused_import) = unused_imports.get(&import.root_id) + && unused_import.unused.contains(&id) + { + continue; + } + + check_redundant_imports.insert(import); + } + } + } + + for import in check_redundant_imports { + self.check_for_redundant_imports(import); + } } } |
