Skip to content

Commit ac035e7

Browse files
committed
Fix redundant import errors for preload extern crate
1 parent 62415e2 commit ac035e7

19 files changed

+246
-28
lines changed

compiler/rustc_lint/src/context/diagnostics.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,21 @@ 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" };
146-
diag.span_label(span, format!("the item `{ident}` is already {introduced} here"));
146+
let span_msg = if span.is_dummy() { "by prelude" } else { "here" };
147+
diag.span_label(
148+
span,
149+
format!("the item `{ident}` is already {introduced} {span_msg}"),
150+
);
147151
}
152+
diag.span_suggestion(
153+
import_span,
154+
"remove this import",
155+
"",
156+
Applicability::MachineApplicable,
157+
);
148158
}
149159
BuiltinLintDiag::DeprecatedMacro(suggestion, span) => {
150160
stability::deprecation_suggestion(diag, "macro", suggestion, span)

compiler/rustc_lint_defs/src/lib.rs

+1-1
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

+65-1
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,
@@ -190,6 +191,40 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
190191
}
191192
}
192193

194+
struct ImportFinderVisitor {
195+
unused_import: Option<UnusedImport>,
196+
root_node_id: ast::NodeId,
197+
node_id: ast::NodeId,
198+
item_span: Span,
199+
}
200+
201+
impl Visitor<'_> for ImportFinderVisitor {
202+
fn visit_item(&mut self, item: &ast::Item) {
203+
match item.kind {
204+
ast::ItemKind::Use(..) if item.span.is_dummy() => return,
205+
_ => {}
206+
}
207+
208+
self.item_span = item.span_with_attributes();
209+
visit::walk_item(self, item);
210+
}
211+
212+
fn visit_use_tree(&mut self, use_tree: &ast::UseTree, id: ast::NodeId, _nested: bool) {
213+
if id == self.root_node_id {
214+
let mut unused_import = UnusedImport {
215+
use_tree: use_tree.clone(),
216+
use_tree_id: id,
217+
item_span: self.item_span,
218+
unused: Default::default(),
219+
};
220+
unused_import.unused.insert(self.node_id);
221+
self.unused_import = Some(unused_import);
222+
}
223+
visit::walk_use_tree(self, use_tree, id);
224+
}
225+
}
226+
227+
#[derive(Debug)]
193228
enum UnusedSpanResult {
194229
Used,
195230
FlatUnused(Span, Span),
@@ -507,7 +542,36 @@ impl Resolver<'_, '_> {
507542
}
508543

509544
for import in check_redundant_imports {
510-
self.check_for_redundant_imports(import);
545+
if let Some(redundant_spans) = self.check_for_redundant_imports(import)
546+
&& let ImportKind::Single { source, id, .. } = import.kind
547+
{
548+
let mut visitor = ImportFinderVisitor {
549+
node_id: id,
550+
root_node_id: import.root_id,
551+
unused_import: None,
552+
item_span: Span::default(),
553+
};
554+
visit::walk_crate(&mut visitor, krate);
555+
if let Some(unused) = visitor.unused_import {
556+
let remove_span =
557+
match calc_unused_spans(&unused, &unused.use_tree, unused.use_tree_id) {
558+
UnusedSpanResult::FlatUnused(_, remove) => remove,
559+
UnusedSpanResult::NestedFullUnused(_, remove) => remove,
560+
UnusedSpanResult::NestedPartialUnused(_, removes) => {
561+
assert_eq!(removes.len(), 1);
562+
removes[0]
563+
}
564+
_ => import.use_span,
565+
};
566+
self.lint_buffer.buffer_lint_with_diagnostic(
567+
UNUSED_IMPORTS,
568+
id,
569+
import.span,
570+
format!("the item `{source}` is imported redundantly"),
571+
BuiltinLintDiag::RedundantImport(redundant_spans, source, remove_span),
572+
);
573+
}
574+
}
511575
}
512576
}
513577
}

compiler/rustc_resolve/src/imports.rs

+9-13
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,13 +1335,11 @@ 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;
1339-
13401342
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
1341-
13421343
self.per_ns(|this, ns| {
13431344
if is_redundant && let Ok(binding) = source_bindings[ns].get() {
13441345
if binding.res() == Res::Err {
@@ -1370,14 +1371,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13701371
let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
13711372
redundant_spans.sort();
13721373
redundant_spans.dedup();
1373-
self.lint_buffer.buffer_lint_with_diagnostic(
1374-
UNUSED_IMPORTS,
1375-
id,
1376-
import.span,
1377-
format!("the item `{source}` is imported redundantly"),
1378-
BuiltinLintDiag::RedundantImport(redundant_spans, source),
1379-
);
1374+
return Some(redundant_spans);
13801375
}
1376+
None
13811377
}
13821378

13831379
fn resolve_glob_import(&mut self, import: Import<'a>) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn item() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//@ compile-flags: --extern aux_issue_121915 --edition 2015
2+
//@ aux-build: aux-issue-121915.rs
3+
4+
extern crate aux_issue_121915;
5+
6+
#[deny(unused_imports)]
7+
fn main() {
8+
use aux_issue_121915;
9+
//~^ ERROR the item `aux_issue_121915` is imported redundantly
10+
aux_issue_121915::item();
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error: the item `aux_issue_121915` is imported redundantly
2+
--> $DIR/redundant-import-issue-121915-2015.rs:8:9
3+
|
4+
LL | extern crate aux_issue_121915;
5+
| ------------------------------ the item `aux_issue_121915` is already imported here
6+
...
7+
LL | use aux_issue_121915;
8+
| ----^^^^^^^^^^^^^^^^- help: remove this import
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/redundant-import-issue-121915-2015.rs:6:8
12+
|
13+
LL | #[deny(unused_imports)]
14+
| ^^^^^^^^^^^^^^
15+
16+
error: aborting due to 1 previous error
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@ compile-flags: --extern aux_issue_121915 --edition 2018
2+
//@ aux-build: aux-issue-121915.rs
3+
4+
#[deny(unused_imports)]
5+
fn main() {
6+
use aux_issue_121915;
7+
//~^ ERROR the item `aux_issue_121915` is imported redundantly
8+
aux_issue_121915::item();
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error: the item `aux_issue_121915` is imported redundantly
2+
--> $DIR/redundant-import-issue-121915.rs:6:9
3+
|
4+
LL | use aux_issue_121915;
5+
| ----^^^^^^^^^^^^^^^^-
6+
| | |
7+
| | the item `aux_issue_121915` is already defined by prelude
8+
| help: remove this import
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/redundant-import-issue-121915.rs:4:8
12+
|
13+
LL | #[deny(unused_imports)]
14+
| ^^^^^^^^^^^^^^
15+
16+
error: aborting due to 1 previous error
17+
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ run-rustfix
2+
//@ compile-flags: --edition 2021
3+
#![deny(unused_imports)]
4+
#![allow(dead_code)]
5+
6+
// Test remove FlatUnused
7+
use std::convert::TryFrom;
8+
//~^ ERROR the item `TryFrom` is imported redundantly
9+
10+
// Test remove NestedFullUnused
11+
use std::convert::{TryInto};
12+
//~^ ERROR the item `TryInto` is imported redundantly
13+
14+
// Test remove NestedPartialUnused
15+
use std::convert::{From, Infallible};
16+
//~^ ERROR the item `From` is imported redundantly
17+
18+
// Test remove both redundant and unused?
19+
// use std::convert::{AsMut, Into};
20+
21+
trait MyTrait {}
22+
impl MyTrait for fn() -> Infallible {}
23+
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();
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error: the item `TryFrom` is imported redundantly
2+
--> $DIR/suggest-remove-issue-121315.rs:7:5
3+
|
4+
LL | use std::convert::TryFrom;
5+
| ----^^^^^^^^^^^^^^^^^^^^^- help: remove this import
6+
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
7+
|
8+
= note: the item `TryFrom` is already defined here
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/suggest-remove-issue-121315.rs:3:9
12+
|
13+
LL | #![deny(unused_imports)]
14+
| ^^^^^^^^^^^^^^
15+
16+
error: the item `TryInto` is imported redundantly
17+
--> $DIR/suggest-remove-issue-121315.rs:11:20
18+
|
19+
LL | use std::convert::{TryInto};
20+
| -------------------^^^^^^^-- help: remove this import
21+
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
22+
|
23+
= note: the item `TryInto` is already defined here
24+
25+
error: the item `From` is imported redundantly
26+
--> $DIR/suggest-remove-issue-121315.rs:15:20
27+
|
28+
LL | use std::convert::{From, Infallible};
29+
| ^^^^--
30+
| |
31+
| help: remove this import
32+
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
33+
|
34+
= note: the item `From` is already defined here
35+
36+
error: aborting due to 3 previous errors
37+

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

+1-1
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

+1-1
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

+1-1
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

+1-1
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)