diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs index cbb3047d88412..bb6647958606c 100644 --- a/compiler/rustc_data_structures/src/owned_slice.rs +++ b/compiler/rustc_data_structures/src/owned_slice.rs @@ -4,7 +4,7 @@ use crate::sync::Lrc; // Use our fake Send/Sync traits when on not parallel compiler, // so that `OwnedSlice` only implements/requires Send/Sync // for parallel compiler builds. -use crate::sync::{Send, Sync}; +use crate::sync; /// An owned slice. /// @@ -33,7 +33,7 @@ pub struct OwnedSlice { // \/ // ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770) #[expect(dead_code)] - owner: Lrc, + owner: Lrc, } /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function. @@ -60,7 +60,7 @@ pub struct OwnedSlice { /// ``` pub fn slice_owned(owner: O, slicer: F) -> OwnedSlice where - O: Send + Sync + 'static, + O: sync::Send + sync::Sync + 'static, F: FnOnce(&O) -> &[u8], { try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok() @@ -71,7 +71,7 @@ where /// See [`slice_owned`] for the infallible version. pub fn try_slice_owned(owner: O, slicer: F) -> Result where - O: Send + Sync + 'static, + O: sync::Send + sync::Sync + 'static, F: FnOnce(&O) -> Result<&[u8], E>, { // We wrap the owner of the bytes in, so it doesn't move. @@ -139,11 +139,11 @@ impl Borrow<[u8]> for OwnedSlice { // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc)`, which is `Send` #[cfg(parallel_compiler)] -unsafe impl Send for OwnedSlice {} +unsafe impl sync::Send for OwnedSlice {} // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc)`, which is `Sync` #[cfg(parallel_compiler)] -unsafe impl Sync for OwnedSlice {} +unsafe impl sync::Sync for OwnedSlice {} #[cfg(test)] mod tests; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8413a1cc0dba9..c8084f662fca2 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -5,7 +5,7 @@ use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; -use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_errors::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::LocalModDefId; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7ff3c523685cc..a0473817d027e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -8,11 +8,11 @@ use crate::def_collector::collect_definitions; use crate::imports::{ImportData, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; -use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; +use crate::Namespace::{MacroNS, TypeNS, ValueNS}; use crate::{errors, BindingKey, MacroData, NameBindingData}; use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot}; -use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError}; -use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError}; +use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError}; +use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError}; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind}; @@ -363,7 +363,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { root_span, root_id, vis: Cell::new(Some(vis)), - used: Cell::new(false), + used: Default::default(), }); self.r.indeterminate_imports.push(import); @@ -853,7 +853,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { span: item.span, module_path: Vec::new(), vis: Cell::new(Some(vis)), - used: Cell::new(used), + used: Cell::new(used.then_some(Used::Other)), }); self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); @@ -1061,7 +1061,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { span, module_path: Vec::new(), vis: Cell::new(Some(ty::Visibility::Restricted(CRATE_DEF_ID))), - used: Cell::new(false), + used: Default::default(), }) }; @@ -1222,7 +1222,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { span, module_path: Vec::new(), vis: Cell::new(Some(vis)), - used: Cell::new(true), + used: Cell::new(Some(Used::Other)), }); let import_binding = self.r.import(binding, import); self.r.define(self.r.graph_root, ident, MacroNS, import_binding); diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 3b1f957c89099..642ca8f6e2ba0 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, } -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>, + unused_imports: FxIndexMap, extern_crate_items: Vec, base_use_tree: Option<&'a ast::UseTree>, base_id: ast::NodeId, @@ -99,9 +100,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 { @@ -196,7 +197,7 @@ enum UnusedSpanResult { } fn calc_unused_spans( - unused_import: &UnusedImport<'_>, + unused_import: &UnusedImport, use_tree: &ast::UseTree, use_tree_id: ast::NodeId, ) -> UnusedSpanResult { @@ -286,7 +287,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() => { @@ -335,7 +336,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())); @@ -482,5 +483,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); + } } } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 02553d5007155..a630727e70dee 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -1,5 +1,5 @@ use crate::{ImplTraitContext, Resolver}; -use rustc_ast::visit::{self, FnKind}; +use rustc_ast::visit::FnKind; use rustc_ast::*; use rustc_expand::expand::AstFragment; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 542aff69e3459..70d4cc011eda5 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -31,8 +31,8 @@ use crate::errors::{AddedMacroUse, ChangeImportBinding, ChangeImportBindingSugge use crate::errors::{ConsiderAddingADerive, ExplicitUnsafeTraits, MaybeMissingMacroRulesName}; use crate::imports::{Import, ImportKind}; use crate::late::{PatternSource, Rib}; -use crate::path_names_to_string; use crate::{errors as errs, BindingKey}; +use crate::{path_names_to_string, Used}; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize}; use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, VisResolutionError}; @@ -1487,7 +1487,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); // Silence the 'unused import' warning we might get, // since this diagnostic already covers that import. - self.record_use(ident, binding, false); + self.record_use(ident, binding, Used::Other); return; } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index a9f7002e564d7..491d6c3b137aa 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -14,8 +14,8 @@ use crate::late::{ ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind, }; use crate::macros::{sub_namespace_match, MacroRulesScope}; -use crate::BindingKey; use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; +use crate::{BindingKey, Used}; use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res}; use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak}; @@ -341,7 +341,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident, ns, parent_scope, - finalize, + finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), ignore_binding, ); if let Ok(binding) = item { @@ -507,7 +507,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns, adjusted_parent_scope, !matches!(scope_set, ScopeSet::Late(..)), - finalize, + finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), ignore_binding, ); match binding { @@ -858,7 +858,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .into_iter() .find_map(|binding| if binding == ignore_binding { None } else { binding }); - if let Some(Finalize { path_span, report_private, .. }) = finalize { + if let Some(Finalize { path_span, report_private, used, .. }) = finalize { let Some(binding) = binding else { return Err((Determined, Weak::No)); }; @@ -902,7 +902,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - self.record_use(ident, binding, restricted_shadowing); + self.record_use(ident, binding, used); return Ok(binding); } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 39e82da6d9dd0..b04512701c708 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -10,9 +10,9 @@ use crate::errors::{ use crate::Determinacy::{self, *}; use crate::Namespace::*; use crate::{module_to_string, names_to_string, ImportSuggestion}; -use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; +use crate::{AmbiguityKind, BindingKey, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; -use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult}; +use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult, Used}; use rustc_ast::NodeId; use rustc_data_structures::fx::FxHashSet; @@ -169,7 +169,7 @@ pub(crate) struct ImportData<'a> { /// The resolution of `module_path`. pub imported_module: Cell>>, pub vis: Cell>, - pub used: Cell, + pub used: Cell>, } /// All imports are unique and allocated on a same arena, @@ -282,7 +282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } self.arenas.alloc_name_binding(NameBindingData { - kind: NameBindingKind::Import { binding, import, used: Cell::new(false) }, + kind: NameBindingKind::Import { binding, import }, ambiguity: None, warn_ambiguity: false, span: import.span, @@ -481,9 +481,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolution.single_imports.remove(&import); }) }); - self.record_use(target, dummy_binding, false); + self.record_use(target, dummy_binding, Used::Other); } else if import.imported_module.get().is_none() { - import.used.set(true); + import.used.set(Some(Used::Other)); if let Some(id) = import.id() { self.used_imports.insert(id); } @@ -1053,11 +1053,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && initial_binding.is_extern_crate() && !initial_binding.is_import() { - this.record_use( - ident, - target_binding, - import.module_path.is_empty(), - ); + let used = if import.module_path.is_empty() { + Used::Scope + } else { + Used::Other + }; + this.record_use(ident, target_binding, used); } } initial_binding.res() @@ -1301,22 +1302,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }); - self.check_for_redundant_imports(ident, import, source_bindings, target_bindings, target); - debug!("(resolving single import) successfully resolved import"); None } - fn check_for_redundant_imports( - &mut self, - ident: Ident, - import: Import<'a>, - source_bindings: &PerNS, Determinacy>>>, - target_bindings: &PerNS>>>, - target: Ident, - ) { + pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) { // This function is only called for single imports. - let ImportKind::Single { id, .. } = import.kind else { unreachable!() }; + let ImportKind::Single { + source, target, ref source_bindings, ref target_bindings, id, .. + } = import.kind + else { + unreachable!() + }; + + // Skip if the import is of the form `use source as target` and source != target. + if source != target { + return; + } // Skip if the import was produced by a macro. if import.parent_scope.expansion != LocalExpnId::ROOT { @@ -1325,7 +1327,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Skip if we are inside a named module (in contrast to an anonymous // module defined by a block). - if let ModuleKind::Def(..) = import.parent_scope.module.kind { + // Skip if the import is public or was used through non scope-based resolution, + // e.g. through a module-relative path. + if self.effective_visibilities.is_exported(self.local_def_id(id)) + || import.used.get() == Some(Used::Other) + { return; } @@ -1367,8 +1373,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { UNUSED_IMPORTS, id, import.span, - format!("the item `{ident}` is imported redundantly"), - BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident), + format!("the item `{source}` is imported redundantly"), + BuiltinLintDiagnostics::RedundantImport(redundant_spans, source), ); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 037179350f044..c38130d7a469b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -7,20 +7,20 @@ //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`. use crate::errors::ImportsCannotReferTo; -use crate::BindingKey; use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding}; +use crate::{BindingKey, Used}; use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; +use rustc_hir::{PrimTy, TraitCandidate}; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; @@ -3491,7 +3491,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // whether they can be shadowed by fresh bindings or not, so force an error. // issues/33118#issuecomment-233962221 (see below) still applies here, // but we have to ignore it for backward compatibility. - self.r.record_use(ident, binding, false); + self.r.record_use(ident, binding, Used::Other); return None; } LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)), @@ -3506,7 +3506,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant or constant pattern. if let Some(binding) = binding { - self.r.record_use(ident, binding, false); + self.r.record_use(ident, binding, Used::Other); } Some(res) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 670fdcfb0d264..4b4e4fd56ec8c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -174,6 +174,23 @@ enum ImplTraitContext { Universal, } +/// Used for tracking import use types which will be used for redundant import checking. +/// ### Used::Scope Example +/// ```rust,compile_fail +/// #![deny(unused_imports)] +/// use std::mem::drop; +/// fn main() { +/// let s = Box::new(32); +/// drop(s); +/// } +/// ``` +/// Used::Other is for other situations like module-relative uses. +#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] +enum Used { + Scope, + Other, +} + #[derive(Debug)] struct BindingError { name: Symbol, @@ -683,7 +700,7 @@ impl<'a> ToNameBinding<'a> for NameBinding<'a> { enum NameBindingKind<'a> { Res(Res), Module(Module<'a>), - Import { binding: NameBinding<'a>, import: Import<'a>, used: Cell }, + Import { binding: NameBinding<'a>, import: Import<'a> }, } impl<'a> NameBindingKind<'a> { @@ -1759,15 +1776,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) { - self.record_use_inner(ident, used_binding, is_lexical_scope, used_binding.warn_ambiguity); + fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, used: Used) { + self.record_use_inner(ident, used_binding, used, used_binding.warn_ambiguity); } fn record_use_inner( &mut self, ident: Ident, used_binding: NameBinding<'a>, - is_lexical_scope: bool, + used: Used, warn_ambiguity: bool, ) { if let Some((b2, kind)) = used_binding.ambiguity { @@ -1785,23 +1802,31 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.ambiguity_errors.push(ambiguity_error); } } - if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind { + if let NameBindingKind::Import { import, binding } = used_binding.kind { // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. - if is_lexical_scope { + if used == Used::Scope { if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { if !entry.introduced_by_item && entry.binding == Some(used_binding) { return; } } } - used.set(true); - import.used.set(true); + let old_used = import.used.get(); + let new_used = Some(used); + if new_used > old_used { + import.used.set(new_used); + } if let Some(id) = import.id() { self.used_imports.insert(id); } self.add_to_glob_map(import, ident); - self.record_use_inner(ident, binding, false, warn_ambiguity || binding.warn_ambiguity); + self.record_use_inner( + ident, + binding, + Used::Other, + warn_ambiguity || binding.warn_ambiguity, + ); } } @@ -1956,7 +1981,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if !entry.is_import() { self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)); } else if entry.introduced_by_item { - self.record_use(ident, binding, false); + self.record_use(ident, binding, Used::Other); } } binding @@ -2086,7 +2111,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let is_import = name_binding.is_import(); let span = name_binding.span; if let Res::Def(DefKind::Fn, _) = res { - self.record_use(ident, name_binding, false); + self.record_use(ident, name_binding, Used::Other); } self.main_def = Some(MainDefinition { res, is_import, span }); } @@ -2147,6 +2172,8 @@ struct Finalize { /// Whether to report privacy errors or silently return "no resolution" for them, /// similarly to speculative resolution. report_private: bool, + /// Tracks whether an item is used in scope or used relatively to a module. + used: Used, } impl Finalize { @@ -2155,7 +2182,7 @@ impl Finalize { } fn with_root_span(node_id: NodeId, path_span: Span, root_span: Span) -> Finalize { - Finalize { node_id, path_span, root_span, report_private: true } + Finalize { node_id, path_span, root_span, report_private: true, used: Used::Other } } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 1001286b6c2d7..15c7478c457d3 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -6,7 +6,7 @@ use crate::errors::{ MacroExpectedFound, RemoveSurroundingDerive, }; use crate::Namespace::*; -use crate::{BuiltinMacroState, Determinacy, MacroData}; +use crate::{BuiltinMacroState, Determinacy, MacroData, Used}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc_ast::expand::StrippedCfgItem; @@ -802,7 +802,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) { Ok(binding) => { let initial_res = initial_binding.map(|initial_binding| { - self.record_use(ident, initial_binding, false); + self.record_use(ident, initial_binding, Used::Other); initial_binding.res() }); let res = binding.res(); diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index 0eb4e88cfad96..7dd023f166b53 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -397,7 +397,6 @@ pub trait OpenOptionsExt { /// /// ```no_run /// # #![feature(rustc_private)] - /// use libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// diff --git a/tests/ui/lint/unused/lint-unused-imports.rs b/tests/ui/lint/unused/lint-unused-imports.rs index 4fa6511c97e1d..88f2baa5da9b3 100644 --- a/tests/ui/lint/unused/lint-unused-imports.rs +++ b/tests/ui/lint/unused/lint-unused-imports.rs @@ -66,7 +66,6 @@ pub mod bar { fn g() { use self::g; //~ ERROR unused import: `self::g` - //~^ ERROR the item `g` is imported redundantly fn f() { self::g(); } @@ -76,7 +75,6 @@ fn g() { #[allow(unused_variables)] fn h() { use test2::foo; //~ ERROR unused import: `test2::foo` - //~^ ERROR the item `foo` is imported redundantly let foo = 0; } diff --git a/tests/ui/lint/unused/lint-unused-imports.stderr b/tests/ui/lint/unused/lint-unused-imports.stderr index 0574ca4569fbf..07684a84a64ff 100644 --- a/tests/ui/lint/unused/lint-unused-imports.stderr +++ b/tests/ui/lint/unused/lint-unused-imports.stderr @@ -34,36 +34,14 @@ error: unused import: `foo::Square` LL | use foo::Square; | ^^^^^^^^^^^ -error: the item `g` is imported redundantly - --> $DIR/lint-unused-imports.rs:68:9 - | -LL | / fn g() { -LL | | use self::g; - | | ^^^^^^^ -LL | | -LL | | fn f() { -LL | | self::g(); -LL | | } -LL | | } - | |_- the item `g` is already defined here - error: unused import: `self::g` --> $DIR/lint-unused-imports.rs:68:9 | LL | use self::g; | ^^^^^^^ -error: the item `foo` is imported redundantly - --> $DIR/lint-unused-imports.rs:78:9 - | -LL | use test2::{foo, bar}; - | --- the item `foo` is already imported here -... -LL | use test2::foo; - | ^^^^^^^^^^ - error: unused import: `test2::foo` - --> $DIR/lint-unused-imports.rs:78:9 + --> $DIR/lint-unused-imports.rs:77:9 | LL | use test2::foo; | ^^^^^^^^^^ @@ -74,5 +52,5 @@ error: unused import: `test::B2` LL | use test::B2; | ^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs new file mode 100644 index 0000000000000..32bdafd012189 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs @@ -0,0 +1,19 @@ +// check-pass +#![warn(unused_imports)] + + +use std::option::Option::Some;//~ WARNING the item `Some` is imported redundantly +use std::option::Option::None; //~ WARNING the item `None` is imported redundantly + +use std::result::Result::Ok;//~ WARNING the item `Ok` is imported redundantly +use std::result::Result::Err;//~ WARNING the item `Err` is imported redundantly +use std::convert::{TryFrom, TryInto}; + +fn main() { + let _a: Option = Some(1); + let _b: Option = None; + let _c: Result = Ok(1); + let _d: Result = Err("error"); + let _e: Result = 8u8.try_into(); + let _f: Result = i32::try_from(8u8); +} diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr new file mode 100644 index 0000000000000..1b09df911eb03 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr @@ -0,0 +1,44 @@ +warning: the item `Some` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:5:5 + | +LL | use std::option::Option::Some; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Some` is already defined here + | +note: the lint level is defined here + --> $DIR/use-redundant-prelude-rust-2015.rs:2:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: the item `None` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:6:5 + | +LL | use std::option::Option::None; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `None` is already defined here + +warning: the item `Ok` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:8:5 + | +LL | use std::result::Result::Ok; + | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Ok` is already defined here + +warning: the item `Err` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:9:5 + | +LL | use std::result::Result::Err; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Err` is already defined here + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs new file mode 100644 index 0000000000000..c6f1856922385 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs @@ -0,0 +1,11 @@ +// check-pass +// edition:2021 +#![warn(unused_imports)] + +use std::convert::TryFrom;//~ WARNING the item `TryFrom` is imported redundantly +use std::convert::TryInto;//~ WARNING the item `TryInto` is imported redundantly + +fn main() { + let _e: Result = 8u8.try_into(); + let _f: Result = i32::try_from(8u8); +} diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr new file mode 100644 index 0000000000000..542356dc996df --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr @@ -0,0 +1,26 @@ +warning: the item `TryFrom` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2021.rs:5:5 + | +LL | use std::convert::TryFrom; + | ^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + | +note: the lint level is defined here + --> $DIR/use-redundant-prelude-rust-2021.rs:3:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: the item `TryInto` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2021.rs:6:5 + | +LL | use std::convert::TryInto; + | ^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryInto` is already defined here + +warning: 2 warnings emitted + diff --git a/tests/ui/rust-2018/remove-extern-crate.fixed b/tests/ui/rust-2018/remove-extern-crate.fixed index 209b91af1ddfb..12f97e2f975d8 100644 --- a/tests/ui/rust-2018/remove-extern-crate.fixed +++ b/tests/ui/rust-2018/remove-extern-crate.fixed @@ -6,6 +6,7 @@ #![warn(rust_2018_idioms)] #![allow(dropping_copy_types)] +#![allow(unused_imports)] //~ WARNING unused extern crate // Shouldn't suggest changing to `use`, as `another_name` diff --git a/tests/ui/rust-2018/remove-extern-crate.rs b/tests/ui/rust-2018/remove-extern-crate.rs index ef3c2db696af2..f7cdc753ef76a 100644 --- a/tests/ui/rust-2018/remove-extern-crate.rs +++ b/tests/ui/rust-2018/remove-extern-crate.rs @@ -6,6 +6,7 @@ #![warn(rust_2018_idioms)] #![allow(dropping_copy_types)] +#![allow(unused_imports)] extern crate core; //~ WARNING unused extern crate // Shouldn't suggest changing to `use`, as `another_name` diff --git a/tests/ui/rust-2018/remove-extern-crate.stderr b/tests/ui/rust-2018/remove-extern-crate.stderr index f752cac8ed630..020db9975c092 100644 --- a/tests/ui/rust-2018/remove-extern-crate.stderr +++ b/tests/ui/rust-2018/remove-extern-crate.stderr @@ -1,5 +1,5 @@ warning: unused extern crate - --> $DIR/remove-extern-crate.rs:10:1 + --> $DIR/remove-extern-crate.rs:11:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: remove it @@ -12,7 +12,7 @@ LL | #![warn(rust_2018_idioms)] = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]` warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:34:5 + --> $DIR/remove-extern-crate.rs:35:5 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | use core; | ~~~ warning: `extern crate` is not idiomatic in the new edition - --> $DIR/remove-extern-crate.rs:44:5 + --> $DIR/remove-extern-crate.rs:45:5 | LL | pub extern crate core; | ^^^^^^^^^^^^^^^^^^^^^^