diff options
| author | yukang <moorekang@gmail.com> | 2024-03-04 10:24:23 +0800 |
|---|---|---|
| committer | yukang <moorekang@gmail.com> | 2024-03-06 21:29:33 +0800 |
| commit | 5a4ff2779eda36d187b4d5b0cd8d18a7a3baa709 (patch) | |
| tree | a00de22dedb43155e9486fc0084d19c8aee1bfdf /compiler/rustc_resolve/src | |
| parent | 62415e2a95a3b0f137636f86f6a904b8ed85798e (diff) | |
| download | rust-5a4ff2779eda36d187b4d5b0cd8d18a7a3baa709.tar.gz rust-5a4ff2779eda36d187b4d5b0cd8d18a7a3baa709.zip | |
Fix redundant import errors for preload extern crate
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/check_unused.rs | 146 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 2 |
2 files changed, 77 insertions, 71 deletions
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 13fec70e0a7..bf1ea2e2709 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -137,6 +137,81 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { self.check_import_as_underscore(item, *id); } } + + fn report_unused_extern_crate_items( + &mut self, + maybe_unused_extern_crates: FxHashMap<ast::NodeId, Span>, + ) { + let tcx = self.r.tcx(); + for extern_crate in &self.extern_crate_items { + let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_'); + + // If the crate is fully unused, we suggest removing it altogether. + // We do this in any edition. + if warn_if_unused { + if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { + self.r.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_EXTERN_CRATES, + extern_crate.id, + span, + "unused extern crate", + BuiltinLintDiag::UnusedExternCrate { + removal_span: extern_crate.span_with_attributes, + }, + ); + continue; + } + } + + // If we are not in Rust 2018 edition, then we don't make any further + // suggestions. + if !tcx.sess.at_least_rust_2018() { + continue; + } + + // If the extern crate has any attributes, they may have funky + // semantics we can't faithfully represent using `use` (most + // notably `#[macro_use]`). Ignore it. + if extern_crate.has_attrs { + continue; + } + + // If the extern crate is renamed, then we cannot suggest replacing it with a use as this + // would not insert the new name into the prelude, where other imports in the crate may be + // expecting it. + if extern_crate.renames { + continue; + } + + // If the extern crate isn't in the extern prelude, + // there is no way it can be written as a `use`. + if !self + .r + .extern_prelude + .get(&extern_crate.ident) + .is_some_and(|entry| !entry.introduced_by_item) + { + continue; + } + + let vis_span = extern_crate + .vis_span + .find_ancestor_inside(extern_crate.span) + .unwrap_or(extern_crate.vis_span); + let ident_span = extern_crate + .ident + .span + .find_ancestor_inside(extern_crate.span) + .unwrap_or(extern_crate.ident.span); + self.r.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_EXTERN_CRATES, + extern_crate.id, + extern_crate.span, + "`extern crate` is not idiomatic in the new edition", + BuiltinLintDiag::ExternCrateNotIdiomatic { vis_span, ident_span }, + ); + } + } } impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { @@ -335,6 +410,8 @@ impl Resolver<'_, '_> { }; visit::walk_crate(&mut visitor, krate); + visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); + 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) { @@ -416,75 +493,6 @@ impl Resolver<'_, '_> { ); } - for extern_crate in visitor.extern_crate_items { - let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_'); - - // If the crate is fully unused, we suggest removing it altogether. - // We do this in any edition. - if warn_if_unused { - if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) { - visitor.r.lint_buffer.buffer_lint_with_diagnostic( - UNUSED_EXTERN_CRATES, - extern_crate.id, - span, - "unused extern crate", - BuiltinLintDiag::UnusedExternCrate { - removal_span: extern_crate.span_with_attributes, - }, - ); - continue; - } - } - - // If we are not in Rust 2018 edition, then we don't make any further - // suggestions. - if !tcx.sess.at_least_rust_2018() { - continue; - } - - // If the extern crate has any attributes, they may have funky - // semantics we can't faithfully represent using `use` (most - // notably `#[macro_use]`). Ignore it. - if extern_crate.has_attrs { - continue; - } - - // If the extern crate is renamed, then we cannot suggest replacing it with a use as this - // would not insert the new name into the prelude, where other imports in the crate may be - // expecting it. - if extern_crate.renames { - continue; - } - - // If the extern crate isn't in the extern prelude, - // there is no way it can be written as a `use`. - if !visitor - .r - .extern_prelude - .get(&extern_crate.ident) - .is_some_and(|entry| !entry.introduced_by_item) - { - continue; - } - - let vis_span = extern_crate - .vis_span - .find_ancestor_inside(extern_crate.span) - .unwrap_or(extern_crate.vis_span); - let ident_span = extern_crate - .ident - .span - .find_ancestor_inside(extern_crate.span) - .unwrap_or(extern_crate.ident.span); - visitor.r.lint_buffer.buffer_lint_with_diagnostic( - UNUSED_EXTERN_CRATES, - extern_crate.id, - extern_crate.span, - "`extern crate` is not idiomatic in the new edition", - BuiltinLintDiag::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() { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 6647a9a2792..80ec69ab318 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1336,9 +1336,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut is_redundant = true; - let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None }; - self.per_ns(|this, ns| { if is_redundant && let Ok(binding) = source_bindings[ns].get() { if binding.res() == Res::Err { |
