Skip to content

Lint for redundant imports #58805

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Mar 31, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/liballoc/borrow.rs
Original file line number Diff line number Diff line change
@@ -135,7 +135,7 @@ impl<T> ToOwned for T
/// Another example showing how to keep `Cow` in a struct:
///
/// ```
/// use std::borrow::{Cow, ToOwned};
/// use std::borrow::Cow;
///
/// struct Items<'a, X: 'a> where [X]: ToOwned<Owned = Vec<X>> {
/// values: Cow<'a, [X]>,
1 change: 0 additions & 1 deletion src/libcore/cell.rs
Original file line number Diff line number Diff line change
@@ -1421,7 +1421,6 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
///
/// ```
/// use std::cell::UnsafeCell;
/// use std::marker::Sync;
///
/// # #[allow(dead_code)]
/// struct NotThreadSafe<T> {
10 changes: 10 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
@@ -483,6 +483,7 @@ pub enum BuiltinLintDiagnostics {
UnknownCrateTypes(Span, String, String),
UnusedImports(String, Vec<(Span, String)>),
NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span },
RedundantImport(Vec<(Span, bool)>, ast::Ident),
}

impl BuiltinLintDiagnostics {
@@ -579,6 +580,15 @@ impl BuiltinLintDiagnostics {
db.span_label(outer_impl_trait_span, "outer `impl Trait`");
db.span_label(inner_impl_trait_span, "nested `impl Trait` here");
}
BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
for (span, is_imported) in spans {
let introduced = if is_imported { "imported" } else { "defined" };
db.span_label(
span,
format!("the item `{}` is already {} here", ident, introduced)
);
}
}
}
}
}
1 change: 0 additions & 1 deletion src/librustc/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
@@ -777,7 +777,6 @@ impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
value: &V)
-> Result<(), E::Error>
{
use crate::ty::codec::TyEncoder;
let start_pos = self.position();

tag.encode(self)?;
1 change: 0 additions & 1 deletion src/librustc_codegen_llvm/context.rs
Original file line number Diff line number Diff line change
@@ -372,7 +372,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
// Returns a Value of the "eh_unwind_resume" lang item if one is defined,
// otherwise declares it as an external function.
fn eh_unwind_resume(&self) -> &'ll Value {
use crate::attributes;
let unwresume = &self.eh_unwind_resume;
if let Some(llfn) = unwresume.get() {
return llfn;
1 change: 0 additions & 1 deletion src/librustc_codegen_ssa/mir/rvalue.rs
Original file line number Diff line number Diff line change
@@ -732,7 +732,6 @@ fn cast_int_to_float<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
// and for everything else LLVM's uitofp works just fine.
use rustc_apfloat::ieee::Single;
use rustc_apfloat::Float;
const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
<< (Single::MAX_EXP - Single::PRECISION as i16);
let max = bx.cx().const_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
1 change: 0 additions & 1 deletion src/librustc_codegen_ssa/traits/type_.rs
Original file line number Diff line number Diff line change
@@ -77,7 +77,6 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
}

fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
use syntax_pos::DUMMY_SP;
if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
return false;
}
2 changes: 1 addition & 1 deletion src/librustc_errors/lib.rs
Original file line number Diff line number Diff line change
@@ -155,7 +155,7 @@ impl CodeSuggestion {
/// Returns the assembled code suggestions and whether they should be shown with an underline.
pub fn splice_lines(&self, cm: &SourceMapperDyn)
-> Vec<(String, Vec<SubstitutionPart>)> {
use syntax_pos::{CharPos, Loc, Pos};
use syntax_pos::{CharPos, Pos};

fn push_trailing(buf: &mut String,
line_opt: Option<&Cow<'_, str>>,
1 change: 0 additions & 1 deletion src/librustc_interface/profile/mod.rs
Original file line number Diff line number Diff line change
@@ -62,7 +62,6 @@ fn total_duration(traces: &[trace::Rec]) -> Duration {
fn profile_queries_thread(r: Receiver<ProfileQueriesMsg>) {
use self::trace::*;
use std::fs::File;
use std::time::{Instant};

let mut profq_msgs: Vec<ProfileQueriesMsg> = vec![];
let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] };
1 change: 0 additions & 1 deletion src/librustc_mir/hair/pattern/mod.rs
Original file line number Diff line number Diff line change
@@ -427,7 +427,6 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {

let mut kind = match (lo, hi) {
(PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
use std::cmp::Ordering;
let cmp = compare_const_vals(
self.tcx,
lo,
2 changes: 0 additions & 2 deletions src/librustc_mir/interpret/operator.rs
Original file line number Diff line number Diff line change
@@ -331,8 +331,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
val: ImmTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
use rustc::mir::UnOp::*;
use rustc_apfloat::ieee::{Single, Double};
use rustc_apfloat::Float;

let layout = val.layout;
let val = val.to_scalar()?;
1 change: 0 additions & 1 deletion src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
@@ -1738,7 +1738,6 @@ impl<'a> Resolver<'a> {
/// just that an error occurred.
pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool)
-> Result<hir::Path, ()> {
use std::iter;
let mut errored = false;

let path = if path_str.starts_with("::") {
94 changes: 93 additions & 1 deletion src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
@@ -7,14 +7,19 @@ use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyErro
use crate::{Resolver, Segment};
use crate::{names_to_string, module_to_string};
use crate::{resolve_error, ResolutionError, Suggestion};
use crate::ModuleKind;
use crate::macros::ParentScope;

use errors::Applicability;

use rustc_data_structures::ptr_key::PtrKey;
use rustc::ty;
use rustc::lint::builtin::BuiltinLintDiagnostics;
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
use rustc::lint::builtin::{
DUPLICATE_MACRO_EXPORTS,
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
UNUSED_IMPORTS,
};
use rustc::hir::def_id::{CrateNum, DefId};
use rustc::hir::def::*;
use rustc::session::DiagnosticMessageId;
@@ -1227,10 +1232,97 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
import[ns] = Some(PathResolution::new(def));
});

self.check_for_redundant_imports(
ident,
directive,
source_bindings,
target_bindings,
target,
);

debug!("(resolving single import) successfully resolved import");
None
}

fn check_for_redundant_imports(
&mut self,
ident: Ident,
directive: &'b ImportDirective<'b>,
source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
target: Ident,
) {
// Skip if the import was produced by a macro.
if directive.parent_scope.expansion != Mark::root() {
return;
}

// Skip if we are inside a named module (in contrast to an anonymous
// module defined by a block).
if let ModuleKind::Def(_, _) = directive.parent_scope.module.kind {
return;
}

let mut is_redundant = PerNS {
value_ns: None,
type_ns: None,
macro_ns: None,
};

let mut redundant_span = PerNS {
value_ns: None,
type_ns: None,
macro_ns: None,
};

self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
if binding.def() == Def::Err {
return;
}

let orig_blacklisted_binding = mem::replace(
&mut this.blacklisted_binding,
target_bindings[ns].get()
);

match this.early_resolve_ident_in_lexical_scope(
target,
ScopeSet::Import(ns),
&directive.parent_scope,
false,
false,
directive.span,
) {
Ok(other_binding) => {
is_redundant[ns] = Some(
binding.def() == other_binding.def()
&& !other_binding.is_ambiguity()
);
redundant_span[ns] =
Some((other_binding.span, other_binding.is_import()));
}
Err(_) => is_redundant[ns] = Some(false)
}

this.blacklisted_binding = orig_blacklisted_binding;
});

if !is_redundant.is_empty() &&
is_redundant.present_items().all(|is_redundant| is_redundant)
{
self.session.buffer_lint_with_diagnostic(
UNUSED_IMPORTS,
directive.id,
directive.span,
&format!("the item `{}` is imported redundantly", ident),
BuiltinLintDiagnostics::RedundantImport(
redundant_span.present_items().collect(),
ident,
),
);
}
}

fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
let module = match directive.imported_module.get().unwrap() {
ModuleOrUniformRoot::Module(module) => module,
5 changes: 0 additions & 5 deletions src/librustc_typeck/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -420,9 +420,6 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
def_id: DefId,
return_ty: Option<Ty<'tcx>>,
) {
use ty::subst::Subst;
use rustc::ty::TypeFoldable;

let predicates = fcx.tcx.predicates_of(def_id);

let generics = tcx.generics_of(def_id);
@@ -1010,8 +1007,6 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>(
span: Span,
id: hir::HirId)
{
use rustc::ty::TypeFoldable;

let empty_env = ty::ParamEnv::empty();

let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id);
2 changes: 0 additions & 2 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
@@ -1069,8 +1069,6 @@ themePicker.onblur = handleThemeButtonsBlur;
}

if cx.shared.include_sources {
use std::path::Component;

let mut hierarchy = Hierarchy::new(OsString::new());
for source in cx.shared.local_sources.iter()
.filter_map(|p| p.0.strip_prefix(&cx.shared.src_root)
3 changes: 1 addition & 2 deletions src/librustdoc/test.rs
Original file line number Diff line number Diff line change
@@ -371,8 +371,7 @@ pub fn make_test(s: &str,
// Uses libsyntax to parse the doctest and find if there's a main fn and the extern
// crate already is included.
let (already_has_main, already_has_extern_crate, found_macro) = crate::syntax::with_globals(|| {
use crate::syntax::{ast, parse::{self, ParseSess}, source_map::FilePathMapping};
use crate::syntax_pos::FileName;
use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping};
use errors::emitter::EmitterWriter;
use errors::Handler;

2 changes: 0 additions & 2 deletions src/test/run-pass/binding/match-arm-statics.rs
Original file line number Diff line number Diff line change
@@ -45,8 +45,6 @@ pub mod glfw {
}

fn issue_6533() {
use glfw;

fn action_to_str(state: glfw::InputState) -> &'static str {
use glfw::{RELEASE, PRESS, REPEAT};
match state {
2 changes: 0 additions & 2 deletions src/test/run-pass/ifmt.rs
Original file line number Diff line number Diff line change
@@ -238,7 +238,6 @@ pub fn main() {
// Basic test to make sure that we can invoke the `write!` macro with an
// fmt::Write instance.
fn test_write() {
use std::fmt::Write;
let mut buf = String::new();
write!(&mut buf, "{}", 3);
{
@@ -267,7 +266,6 @@ fn test_print() {
// Just make sure that the macros are defined, there's not really a lot that we
// can do with them just yet (to test the output)
fn test_format_args() {
use std::fmt::Write;
let mut buf = String::new();
{
let w = &mut buf;
1 change: 0 additions & 1 deletion src/test/run-pass/invalid_const_promotion.rs
Original file line number Diff line number Diff line change
@@ -25,7 +25,6 @@ fn foo() {
#[cfg(unix)]
fn check_status(status: std::process::ExitStatus)
{
use libc;
use std::os::unix::process::ExitStatusExt;

assert!(status.signal() == Some(libc::SIGILL)
1 change: 0 additions & 1 deletion src/test/run-pass/issues/issue-38556.rs
Original file line number Diff line number Diff line change
@@ -9,6 +9,5 @@ macro_rules! reexport {
reexport!();

fn main() {
use Bar;
fn f(_: Bar) {}
}
1 change: 0 additions & 1 deletion src/test/run-pass/issues/issue-39367.rs
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@ fn arena() -> &'static ArenaSet<Vec<u8>> {
fn require_sync<T: Sync>(_: &T) { }
unsafe fn __stability() -> &'static ArenaSet<Vec<u8>> {
use std::mem::transmute;
use std::boxed::Box;
static mut DATA: *const ArenaSet<Vec<u8>> = 0 as *const ArenaSet<Vec<u8>>;

static mut ONCE: Once = ONCE_INIT;
1 change: 0 additions & 1 deletion src/test/run-pass/out-of-stack.rs
Original file line number Diff line number Diff line change
@@ -36,7 +36,6 @@ fn loud_recurse() {
#[cfg(unix)]
fn check_status(status: std::process::ExitStatus)
{
use libc;
use std::os::unix::process::ExitStatusExt;

assert!(!status.success());
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@
// compile-flags:--extern xcrate
// edition:2018

#![allow(unused_imports)]

use xcrate::Z;

fn f() {
Original file line number Diff line number Diff line change
@@ -28,7 +28,6 @@ where T : Convert<U>
}

fn main() {
use std::default::Default;
// T = i16, U = u32
test(22_i16, Default::default(), 2, 4);

2 changes: 2 additions & 0 deletions src/test/ui/lint/lint-unused-imports.rs
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@ mod bar {

fn g() {
use self::g; //~ ERROR unused import: `self::g`
//~^ ERROR the item `g` is imported redundantly
fn f() {
self::g();
}
@@ -75,6 +76,7 @@ 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;
}

Loading