Skip to content

Commit 290be1b

Browse files
committed
Fix redundant import errors for preload extern crate
1 parent 1508a03 commit 290be1b

16 files changed

+159
-91
lines changed

compiler/rustc_lint/src/context/diagnostics.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
140140
);
141141
}
142142
}
143-
BuiltinLintDiag::RedundantImport(spans, ident) => {
143+
BuiltinLintDiag::RedundantImport(spans, ident, import_span) => {
144144
for (span, is_imported) in spans {
145145
let introduced = if is_imported { "imported" } else { "defined" };
146146
let span_msg = if span.is_dummy() { "by prelude" } else { "here" };
@@ -149,6 +149,12 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
149149
format!("the item `{ident}` is already {introduced} {span_msg}"),
150150
);
151151
}
152+
diag.span_suggestion(
153+
import_span,
154+
"remove this import",
155+
"",
156+
Applicability::MachineApplicable,
157+
);
152158
}
153159
BuiltinLintDiag::DeprecatedMacro(suggestion, span) => {
154160
stability::deprecation_suggestion(diag, "macro", suggestion, span)

compiler/rustc_lint_defs/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ pub enum BuiltinLintDiag {
577577
ElidedLifetimesInPaths(usize, Span, bool, Span),
578578
UnknownCrateTypes(Span, String, String),
579579
UnusedImports(String, Vec<(Span, String)>, Option<Span>),
580-
RedundantImport(Vec<(Span, bool)>, Ident),
580+
RedundantImport(Vec<(Span, bool)>, Ident, Span),
581581
DeprecatedMacro(Option<Symbol>, Span),
582582
MissingAbi(Span, Abi),
583583
UnusedDocComment(Span),

compiler/rustc_resolve/src/check_unused.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use rustc_session::lint::BuiltinLintDiag;
3939
use rustc_span::symbol::{kw, Ident};
4040
use rustc_span::{Span, DUMMY_SP};
4141

42+
#[derive(Debug)]
4243
struct UnusedImport {
4344
use_tree: ast::UseTree,
4445
use_tree_id: ast::NodeId,
@@ -265,6 +266,40 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
265266
}
266267
}
267268

269+
struct ImportFinderVisitor {
270+
unused_import: Option<UnusedImport>,
271+
root_node_id: ast::NodeId,
272+
node_id: ast::NodeId,
273+
item_span: Span,
274+
}
275+
276+
impl Visitor<'_> for ImportFinderVisitor {
277+
fn visit_item(&mut self, item: &ast::Item) {
278+
match item.kind {
279+
ast::ItemKind::Use(..) if item.span.is_dummy() => return,
280+
_ => {}
281+
}
282+
283+
self.item_span = item.span_with_attributes();
284+
visit::walk_item(self, item);
285+
}
286+
287+
fn visit_use_tree(&mut self, use_tree: &ast::UseTree, id: ast::NodeId, _nested: bool) {
288+
if id == self.root_node_id {
289+
let mut unused_import = UnusedImport {
290+
use_tree: use_tree.clone(),
291+
use_tree_id: id,
292+
item_span: self.item_span,
293+
unused: Default::default(),
294+
};
295+
unused_import.unused.insert(self.node_id);
296+
self.unused_import = Some(unused_import);
297+
}
298+
visit::walk_use_tree(self, use_tree, id);
299+
}
300+
}
301+
302+
#[derive(Debug)]
268303
enum UnusedSpanResult {
269304
Used,
270305
FlatUnused(Span, Span),
@@ -515,7 +550,36 @@ impl Resolver<'_, '_> {
515550
}
516551

517552
for import in check_redundant_imports {
518-
self.check_for_redundant_imports(import);
553+
if let Some(redundant_spans) = self.check_for_redundant_imports(import)
554+
&& let ImportKind::Single { source, id, .. } = import.kind
555+
{
556+
let mut visitor = ImportFinderVisitor {
557+
node_id: id,
558+
root_node_id: import.root_id,
559+
unused_import: None,
560+
item_span: Span::default(),
561+
};
562+
visit::walk_crate(&mut visitor, krate);
563+
if let Some(unused) = visitor.unused_import {
564+
let remove_span =
565+
match calc_unused_spans(&unused, &unused.use_tree, unused.use_tree_id) {
566+
UnusedSpanResult::FlatUnused(_, remove) => remove,
567+
UnusedSpanResult::NestedFullUnused(_, remove) => remove,
568+
UnusedSpanResult::NestedPartialUnused(_, removes) => {
569+
assert_eq!(removes.len(), 1);
570+
removes[0]
571+
}
572+
_ => import.use_span,
573+
};
574+
self.lint_buffer.buffer_lint_with_diagnostic(
575+
UNUSED_IMPORTS,
576+
id,
577+
import.span,
578+
format!("the item `{source}` is imported redundantly"),
579+
BuiltinLintDiag::RedundantImport(redundant_spans, source, remove_span),
580+
);
581+
}
582+
}
519583
}
520584
}
521585
}

compiler/rustc_resolve/src/imports.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,7 +1306,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13061306
None
13071307
}
13081308

1309-
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) {
1309+
pub(crate) fn check_for_redundant_imports(
1310+
&mut self,
1311+
import: Import<'a>,
1312+
) -> Option<Vec<(Span, bool)>> {
13101313
// This function is only called for single imports.
13111314
let ImportKind::Single {
13121315
source, target, ref source_bindings, ref target_bindings, id, ..
@@ -1317,12 +1320,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13171320

13181321
// Skip if the import is of the form `use source as target` and source != target.
13191322
if source != target {
1320-
return;
1323+
return None;
13211324
}
13221325

13231326
// Skip if the import was produced by a macro.
13241327
if import.parent_scope.expansion != LocalExpnId::ROOT {
1325-
return;
1328+
return None;
13261329
}
13271330

13281331
// Skip if we are inside a named module (in contrast to an anonymous
@@ -1332,7 +1335,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13321335
if import.used.get() == Some(Used::Other)
13331336
|| self.effective_visibilities.is_exported(self.local_def_id(id))
13341337
{
1335-
return;
1338+
return None;
13361339
}
13371340

13381341
let mut is_redundant = true;
@@ -1368,14 +1371,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13681371
let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
13691372
redundant_spans.sort();
13701373
redundant_spans.dedup();
1371-
self.lint_buffer.buffer_lint_with_diagnostic(
1372-
UNUSED_IMPORTS,
1373-
id,
1374-
import.span,
1375-
format!("the item `{source}` is imported redundantly"),
1376-
BuiltinLintDiag::RedundantImport(redundant_spans, source),
1377-
);
1374+
return Some(redundant_spans);
13781375
}
1376+
None
13791377
}
13801378

13811379
fn resolve_glob_import(&mut self, import: Import<'a>) {

tests/ui/imports/redundant-import-issue-121915-2015.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | extern crate aux_issue_121915;
55
| ------------------------------ the item `aux_issue_121915` is already imported here
66
...
77
LL | use aux_issue_121915;
8-
| ^^^^^^^^^^^^^^^^
8+
| ----^^^^^^^^^^^^^^^^- help: remove this import
99
|
1010
note: the lint level is defined here
1111
--> $DIR/redundant-import-issue-121915-2015.rs:6:8

tests/ui/imports/redundant-import-issue-121915.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: the item `aux_issue_121915` is imported redundantly
22
--> $DIR/redundant-import-issue-121915.rs:6:9
33
|
44
LL | use aux_issue_121915;
5-
| ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by prelude
5+
| ----^^^^^^^^^^^^^^^^-
6+
| | |
7+
| | the item `aux_issue_121915` is already defined by prelude
8+
| help: remove this import
69
|
710
note: the lint level is defined here
811
--> $DIR/redundant-import-issue-121915.rs:4:8
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ run-rustfix
2+
//@ compile-flags: --edition 2021
3+
#![deny(unused_imports)]
4+
#![allow(dead_code)]
5+
6+
// Test remove FlatUnused
7+
//~^ ERROR the item `TryFrom` is imported redundantly
8+
9+
// Test remove NestedFullUnused
10+
//~^ ERROR the item `TryInto` is imported redundantly
11+
12+
// Test remove NestedPartialUnused
13+
use std::convert::{Infallible};
14+
//~^ ERROR the item `From` is imported redundantly
15+
16+
// Test remove both redundant and unused?
17+
// use std::convert::{AsMut, Into};
18+
19+
trait MyTrait {}
20+
impl MyTrait for fn() -> Infallible {}
21+
22+
fn main() {
23+
let _ = u32::try_from(5i32);
24+
let _a: i32 = u32::try_into(5u32).unwrap();
25+
let _a: String = String::from("hello anan");
26+
//let _a: u32 = (5i32).into();
27+
}
Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,29 @@
1+
//@ run-rustfix
12
//@ compile-flags: --edition 2021
23
#![deny(unused_imports)]
34
#![allow(dead_code)]
45

5-
fn test0() {
6-
// Test remove FlatUnused
7-
use std::convert::TryFrom;
8-
//~^ ERROR the item `TryFrom` is imported redundantly
9-
let _ = u32::try_from(5i32);
10-
}
11-
12-
fn test1() {
13-
// FIXME(yukang) Test remove NestedFullUnused
14-
use std::convert::{TryFrom, TryInto};
15-
//~^ ERROR the item `TryFrom` is imported redundantly
16-
//~| ERROR the item `TryInto` is imported redundantly
6+
// Test remove FlatUnused
7+
use std::convert::TryFrom;
8+
//~^ ERROR the item `TryFrom` is imported redundantly
179

18-
let _ = u32::try_from(5i32);
19-
let _a: i32 = u32::try_into(5u32).unwrap();
20-
}
10+
// Test remove NestedFullUnused
11+
use std::convert::{TryInto};
12+
//~^ ERROR the item `TryInto` is imported redundantly
2113

22-
fn test2() {
23-
// FIXME(yukang): Test remove both redundant and unused
24-
use std::convert::{AsMut, Into};
25-
//~^ ERROR unused import: `AsMut`
26-
//~| ERROR the item `Into` is imported redundantly
14+
// Test remove NestedPartialUnused
15+
use std::convert::{From, Infallible};
16+
//~^ ERROR the item `From` is imported redundantly
2717

28-
let _a: u32 = (5u8).into();
29-
}
18+
// Test remove both redundant and unused?
19+
// use std::convert::{AsMut, Into};
3020

31-
fn test3() {
32-
// Test remove NestedPartialUnused
33-
use std::convert::{From, Infallible};
34-
//~^ ERROR unused import: `From`
21+
trait MyTrait {}
22+
impl MyTrait for fn() -> Infallible {}
3523

36-
trait MyTrait {}
37-
impl MyTrait for fn() -> Infallible {}
24+
fn main() {
25+
let _ = u32::try_from(5i32);
26+
let _a: i32 = u32::try_into(5u32).unwrap();
27+
let _a: String = String::from("hello anan");
28+
//let _a: u32 = (5i32).into();
3829
}
39-
40-
fn main() {}
Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,37 @@
11
error: the item `TryFrom` is imported redundantly
2-
--> $DIR/suggest-remove-issue-121315.rs:7:9
2+
--> $DIR/suggest-remove-issue-121315.rs:7:5
33
|
4-
LL | use std::convert::TryFrom;
5-
| ^^^^^^^^^^^^^^^^^^^^^
4+
LL | use std::convert::TryFrom;
5+
| ----^^^^^^^^^^^^^^^^^^^^^- help: remove this import
66
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
77
|
88
= note: the item `TryFrom` is already defined here
99
|
1010
note: the lint level is defined here
11-
--> $DIR/suggest-remove-issue-121315.rs:2:9
11+
--> $DIR/suggest-remove-issue-121315.rs:3:9
1212
|
1313
LL | #![deny(unused_imports)]
1414
| ^^^^^^^^^^^^^^
1515

16-
error: the item `TryFrom` is imported redundantly
17-
--> $DIR/suggest-remove-issue-121315.rs:14:24
18-
|
19-
LL | use std::convert::{TryFrom, TryInto};
20-
| ^^^^^^^
21-
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
22-
|
23-
= note: the item `TryFrom` is already defined here
24-
2516
error: the item `TryInto` is imported redundantly
26-
--> $DIR/suggest-remove-issue-121315.rs:14:33
17+
--> $DIR/suggest-remove-issue-121315.rs:11:20
2718
|
28-
LL | use std::convert::{TryFrom, TryInto};
29-
| ^^^^^^^
19+
LL | use std::convert::{TryInto};
20+
| -------------------^^^^^^^-- help: remove this import
3021
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
3122
|
3223
= note: the item `TryInto` is already defined here
3324

34-
error: unused import: `AsMut`
35-
--> $DIR/suggest-remove-issue-121315.rs:24:24
36-
|
37-
LL | use std::convert::{AsMut, Into};
38-
| ^^^^^
39-
40-
error: the item `Into` is imported redundantly
41-
--> $DIR/suggest-remove-issue-121315.rs:24:31
25+
error: the item `From` is imported redundantly
26+
--> $DIR/suggest-remove-issue-121315.rs:15:20
4227
|
43-
LL | use std::convert::{AsMut, Into};
44-
| ^^^^
28+
LL | use std::convert::{From, Infallible};
29+
| ^^^^--
30+
| |
31+
| help: remove this import
4532
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
4633
|
47-
= note: the item `Into` is already defined here
48-
49-
error: unused import: `From`
50-
--> $DIR/suggest-remove-issue-121315.rs:33:24
51-
|
52-
LL | use std::convert::{From, Infallible};
53-
| ^^^^
34+
= note: the item `From` is already defined here
5435

55-
error: aborting due to 6 previous errors
36+
error: aborting due to 3 previous errors
5637

tests/ui/lint/unused/issue-59896.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | struct S;
55
| --------- the item `S` is already defined here
66
...
77
LL | use S;
8-
| ^
8+
| ----^- help: remove this import
99
|
1010
note: the lint level is defined here
1111
--> $DIR/issue-59896.rs:1:9

tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | use bar::*;
55
| ------ the item `Foo` is already imported here
66
...
77
LL | use bar::Foo;
8-
| ^^^^^^^^
8+
| ----^^^^^^^^- help: remove this import
99
|
1010
note: the lint level is defined here
1111
--> $DIR/use-redundant-glob-parent.rs:2:9

tests/ui/lint/use-redundant/use-redundant-glob.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ warning: the item `Foo` is imported redundantly
44
LL | use bar::*;
55
| ------ the item `Foo` is already imported here
66
LL | use bar::Foo;
7-
| ^^^^^^^^
7+
| ----^^^^^^^^- help: remove this import
88
|
99
note: the lint level is defined here
1010
--> $DIR/use-redundant-glob.rs:2:9

tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: the item `String` is imported redundantly
22
--> $DIR/use-redundant-issue-71450.rs:26:13
33
|
44
LL | use std::string::String;
5-
| ^^^^^^^^^^^^^^^^^^^
5+
| ----^^^^^^^^^^^^^^^^^^^- help: remove this import
66
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
77
|
88
= note: the item `String` is already defined here

0 commit comments

Comments
 (0)