Skip to content

Commit dffdd8f

Browse files
authored
Rollup merge of rust-lang#58805 - fabric-and-ink:redundant_import, r=petrochenkov
Lint for redundant imports Add lint for redundant imports. The changes are suggested by @petrochenkov. Closes rust-lang#10178.
2 parents a89c03a + c1d5314 commit dffdd8f

File tree

30 files changed

+198
-42
lines changed

30 files changed

+198
-42
lines changed

Diff for: src/liballoc/borrow.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ impl<T> ToOwned for T
135135
/// Another example showing how to keep `Cow` in a struct:
136136
///
137137
/// ```
138-
/// use std::borrow::{Cow, ToOwned};
138+
/// use std::borrow::Cow;
139139
///
140140
/// struct Items<'a, X: 'a> where [X]: ToOwned<Owned = Vec<X>> {
141141
/// values: Cow<'a, [X]>,

Diff for: src/libcore/cell.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1421,7 +1421,6 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
14211421
///
14221422
/// ```
14231423
/// use std::cell::UnsafeCell;
1424-
/// use std::marker::Sync;
14251424
///
14261425
/// # #[allow(dead_code)]
14271426
/// struct NotThreadSafe<T> {

Diff for: src/librustc/lint/builtin.rs

+10
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ pub enum BuiltinLintDiagnostics {
483483
UnknownCrateTypes(Span, String, String),
484484
UnusedImports(String, Vec<(Span, String)>),
485485
NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span },
486+
RedundantImport(Vec<(Span, bool)>, ast::Ident),
486487
}
487488

488489
impl BuiltinLintDiagnostics {
@@ -579,6 +580,15 @@ impl BuiltinLintDiagnostics {
579580
db.span_label(outer_impl_trait_span, "outer `impl Trait`");
580581
db.span_label(inner_impl_trait_span, "nested `impl Trait` here");
581582
}
583+
BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
584+
for (span, is_imported) in spans {
585+
let introduced = if is_imported { "imported" } else { "defined" };
586+
db.span_label(
587+
span,
588+
format!("the item `{}` is already {} here", ident, introduced)
589+
);
590+
}
591+
}
582592
}
583593
}
584594
}

Diff for: src/librustc/ty/query/on_disk_cache.rs

-1
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,6 @@ impl<'enc, 'a, 'tcx, E> CacheEncoder<'enc, 'a, 'tcx, E>
777777
value: &V)
778778
-> Result<(), E::Error>
779779
{
780-
use crate::ty::codec::TyEncoder;
781780
let start_pos = self.position();
782781

783782
tag.encode(self)?;

Diff for: src/librustc_codegen_llvm/context.rs

-1
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
372372
// Returns a Value of the "eh_unwind_resume" lang item if one is defined,
373373
// otherwise declares it as an external function.
374374
fn eh_unwind_resume(&self) -> &'ll Value {
375-
use crate::attributes;
376375
let unwresume = &self.eh_unwind_resume;
377376
if let Some(llfn) = unwresume.get() {
378377
return llfn;

Diff for: src/librustc_codegen_ssa/mir/rvalue.rs

-1
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,6 @@ fn cast_int_to_float<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
732732
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
733733
// and for everything else LLVM's uitofp works just fine.
734734
use rustc_apfloat::ieee::Single;
735-
use rustc_apfloat::Float;
736735
const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
737736
<< (Single::MAX_EXP - Single::PRECISION as i16);
738737
let max = bx.cx().const_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);

Diff for: src/librustc_codegen_ssa/traits/type_.rs

-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
7777
}
7878

7979
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
80-
use syntax_pos::DUMMY_SP;
8180
if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
8281
return false;
8382
}

Diff for: src/librustc_errors/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl CodeSuggestion {
155155
/// Returns the assembled code suggestions and whether they should be shown with an underline.
156156
pub fn splice_lines(&self, cm: &SourceMapperDyn)
157157
-> Vec<(String, Vec<SubstitutionPart>)> {
158-
use syntax_pos::{CharPos, Loc, Pos};
158+
use syntax_pos::{CharPos, Pos};
159159

160160
fn push_trailing(buf: &mut String,
161161
line_opt: Option<&Cow<'_, str>>,

Diff for: src/librustc_interface/profile/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ fn total_duration(traces: &[trace::Rec]) -> Duration {
6262
fn profile_queries_thread(r: Receiver<ProfileQueriesMsg>) {
6363
use self::trace::*;
6464
use std::fs::File;
65-
use std::time::{Instant};
6665

6766
let mut profq_msgs: Vec<ProfileQueriesMsg> = vec![];
6867
let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] };

Diff for: src/librustc_mir/hair/pattern/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,6 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
427427

428428
let mut kind = match (lo, hi) {
429429
(PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => {
430-
use std::cmp::Ordering;
431430
let cmp = compare_const_vals(
432431
self.tcx,
433432
lo,

Diff for: src/librustc_mir/interpret/operator.rs

-2
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
331331
val: ImmTy<'tcx, M::PointerTag>,
332332
) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
333333
use rustc::mir::UnOp::*;
334-
use rustc_apfloat::ieee::{Single, Double};
335-
use rustc_apfloat::Float;
336334

337335
let layout = val.layout;
338336
let val = val.to_scalar()?;

Diff for: src/librustc_resolve/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1738,7 +1738,6 @@ impl<'a> Resolver<'a> {
17381738
/// just that an error occurred.
17391739
pub fn resolve_str_path_error(&mut self, span: Span, path_str: &str, is_value: bool)
17401740
-> Result<hir::Path, ()> {
1741-
use std::iter;
17421741
let mut errored = false;
17431742

17441743
let path = if path_str.starts_with("::") {

Diff for: src/librustc_resolve/resolve_imports.rs

+93-1
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyErro
77
use crate::{Resolver, Segment};
88
use crate::{names_to_string, module_to_string};
99
use crate::{resolve_error, ResolutionError, Suggestion};
10+
use crate::ModuleKind;
1011
use crate::macros::ParentScope;
1112

1213
use errors::Applicability;
1314

1415
use rustc_data_structures::ptr_key::PtrKey;
1516
use rustc::ty;
1617
use rustc::lint::builtin::BuiltinLintDiagnostics;
17-
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
18+
use rustc::lint::builtin::{
19+
DUPLICATE_MACRO_EXPORTS,
20+
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
21+
UNUSED_IMPORTS,
22+
};
1823
use rustc::hir::def_id::{CrateNum, DefId};
1924
use rustc::hir::def::*;
2025
use rustc::session::DiagnosticMessageId;
@@ -1227,10 +1232,97 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
12271232
import[ns] = Some(PathResolution::new(def));
12281233
});
12291234

1235+
self.check_for_redundant_imports(
1236+
ident,
1237+
directive,
1238+
source_bindings,
1239+
target_bindings,
1240+
target,
1241+
);
1242+
12301243
debug!("(resolving single import) successfully resolved import");
12311244
None
12321245
}
12331246

1247+
fn check_for_redundant_imports(
1248+
&mut self,
1249+
ident: Ident,
1250+
directive: &'b ImportDirective<'b>,
1251+
source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
1252+
target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
1253+
target: Ident,
1254+
) {
1255+
// Skip if the import was produced by a macro.
1256+
if directive.parent_scope.expansion != Mark::root() {
1257+
return;
1258+
}
1259+
1260+
// Skip if we are inside a named module (in contrast to an anonymous
1261+
// module defined by a block).
1262+
if let ModuleKind::Def(_, _) = directive.parent_scope.module.kind {
1263+
return;
1264+
}
1265+
1266+
let mut is_redundant = PerNS {
1267+
value_ns: None,
1268+
type_ns: None,
1269+
macro_ns: None,
1270+
};
1271+
1272+
let mut redundant_span = PerNS {
1273+
value_ns: None,
1274+
type_ns: None,
1275+
macro_ns: None,
1276+
};
1277+
1278+
self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
1279+
if binding.def() == Def::Err {
1280+
return;
1281+
}
1282+
1283+
let orig_blacklisted_binding = mem::replace(
1284+
&mut this.blacklisted_binding,
1285+
target_bindings[ns].get()
1286+
);
1287+
1288+
match this.early_resolve_ident_in_lexical_scope(
1289+
target,
1290+
ScopeSet::Import(ns),
1291+
&directive.parent_scope,
1292+
false,
1293+
false,
1294+
directive.span,
1295+
) {
1296+
Ok(other_binding) => {
1297+
is_redundant[ns] = Some(
1298+
binding.def() == other_binding.def()
1299+
&& !other_binding.is_ambiguity()
1300+
);
1301+
redundant_span[ns] =
1302+
Some((other_binding.span, other_binding.is_import()));
1303+
}
1304+
Err(_) => is_redundant[ns] = Some(false)
1305+
}
1306+
1307+
this.blacklisted_binding = orig_blacklisted_binding;
1308+
});
1309+
1310+
if !is_redundant.is_empty() &&
1311+
is_redundant.present_items().all(|is_redundant| is_redundant)
1312+
{
1313+
self.session.buffer_lint_with_diagnostic(
1314+
UNUSED_IMPORTS,
1315+
directive.id,
1316+
directive.span,
1317+
&format!("the item `{}` is imported redundantly", ident),
1318+
BuiltinLintDiagnostics::RedundantImport(
1319+
redundant_span.present_items().collect(),
1320+
ident,
1321+
),
1322+
);
1323+
}
1324+
}
1325+
12341326
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
12351327
let module = match directive.imported_module.get().unwrap() {
12361328
ModuleOrUniformRoot::Module(module) => module,

Diff for: src/librustc_typeck/check/wfcheck.rs

-5
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,6 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
420420
def_id: DefId,
421421
return_ty: Option<Ty<'tcx>>,
422422
) {
423-
use ty::subst::Subst;
424-
use rustc::ty::TypeFoldable;
425-
426423
let predicates = fcx.tcx.predicates_of(def_id);
427424

428425
let generics = tcx.generics_of(def_id);
@@ -1010,8 +1007,6 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>(
10101007
span: Span,
10111008
id: hir::HirId)
10121009
{
1013-
use rustc::ty::TypeFoldable;
1014-
10151010
let empty_env = ty::ParamEnv::empty();
10161011

10171012
let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id);

Diff for: src/librustdoc/html/render.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1069,8 +1069,6 @@ themePicker.onblur = handleThemeButtonsBlur;
10691069
}
10701070

10711071
if cx.shared.include_sources {
1072-
use std::path::Component;
1073-
10741072
let mut hierarchy = Hierarchy::new(OsString::new());
10751073
for source in cx.shared.local_sources.iter()
10761074
.filter_map(|p| p.0.strip_prefix(&cx.shared.src_root)

Diff for: src/librustdoc/test.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,7 @@ pub fn make_test(s: &str,
371371
// Uses libsyntax to parse the doctest and find if there's a main fn and the extern
372372
// crate already is included.
373373
let (already_has_main, already_has_extern_crate, found_macro) = crate::syntax::with_globals(|| {
374-
use crate::syntax::{ast, parse::{self, ParseSess}, source_map::FilePathMapping};
375-
use crate::syntax_pos::FileName;
374+
use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping};
376375
use errors::emitter::EmitterWriter;
377376
use errors::Handler;
378377

Diff for: src/test/run-pass/binding/match-arm-statics.rs

-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ pub mod glfw {
4545
}
4646

4747
fn issue_6533() {
48-
use glfw;
49-
5048
fn action_to_str(state: glfw::InputState) -> &'static str {
5149
use glfw::{RELEASE, PRESS, REPEAT};
5250
match state {

Diff for: src/test/run-pass/ifmt.rs

-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,6 @@ pub fn main() {
238238
// Basic test to make sure that we can invoke the `write!` macro with an
239239
// fmt::Write instance.
240240
fn test_write() {
241-
use std::fmt::Write;
242241
let mut buf = String::new();
243242
write!(&mut buf, "{}", 3);
244243
{
@@ -267,7 +266,6 @@ fn test_print() {
267266
// Just make sure that the macros are defined, there's not really a lot that we
268267
// can do with them just yet (to test the output)
269268
fn test_format_args() {
270-
use std::fmt::Write;
271269
let mut buf = String::new();
272270
{
273271
let w = &mut buf;

Diff for: src/test/run-pass/invalid_const_promotion.rs

-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ fn foo() {
2525
#[cfg(unix)]
2626
fn check_status(status: std::process::ExitStatus)
2727
{
28-
use libc;
2928
use std::os::unix::process::ExitStatusExt;
3029

3130
assert!(status.signal() == Some(libc::SIGILL)

Diff for: src/test/run-pass/issues/issue-38556.rs

-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@ macro_rules! reexport {
99
reexport!();
1010

1111
fn main() {
12-
use Bar;
1312
fn f(_: Bar) {}
1413
}

Diff for: src/test/run-pass/issues/issue-39367.rs

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ fn arena() -> &'static ArenaSet<Vec<u8>> {
1515
fn require_sync<T: Sync>(_: &T) { }
1616
unsafe fn __stability() -> &'static ArenaSet<Vec<u8>> {
1717
use std::mem::transmute;
18-
use std::boxed::Box;
1918
static mut DATA: *const ArenaSet<Vec<u8>> = 0 as *const ArenaSet<Vec<u8>>;
2019

2120
static mut ONCE: Once = ONCE_INIT;

Diff for: src/test/run-pass/out-of-stack.rs

-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ fn loud_recurse() {
3636
#[cfg(unix)]
3737
fn check_status(status: std::process::ExitStatus)
3838
{
39-
use libc;
4039
use std::os::unix::process::ExitStatusExt;
4140

4241
assert!(!status.success());

Diff for: src/test/run-pass/rfcs/rfc-2126-extern-absolute-paths/basic.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// compile-flags:--extern xcrate
55
// edition:2018
66

7+
#![allow(unused_imports)]
8+
79
use xcrate::Z;
810

911
fn f() {

Diff for: src/test/run-pass/traits/traits-multidispatch-infer-convert-target.rs

-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ where T : Convert<U>
2828
}
2929

3030
fn main() {
31-
use std::default::Default;
3231
// T = i16, U = u32
3332
test(22_i16, Default::default(), 2, 4);
3433

Diff for: src/test/ui/lint/lint-unused-imports.rs

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ mod bar {
6666

6767
fn g() {
6868
use self::g; //~ ERROR unused import: `self::g`
69+
//~^ ERROR the item `g` is imported redundantly
6970
fn f() {
7071
self::g();
7172
}
@@ -75,6 +76,7 @@ fn g() {
7576
#[allow(unused_variables)]
7677
fn h() {
7778
use test2::foo; //~ ERROR unused import: `test2::foo`
79+
//~^ ERROR the item `foo` is imported redundantly
7880
let foo = 0;
7981
}
8082

0 commit comments

Comments
 (0)