Skip to content

Commit 4e5c823

Browse files
committed
Fix redundant import errors for preload extern crate
1 parent bdde2a8 commit 4e5c823

18 files changed

+245
-27
lines changed

compiler/rustc_lint/src/context/diagnostics.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,21 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
103103
);
104104
}
105105
}
106-
BuiltinLintDiag::RedundantImport(spans, ident) => {
106+
BuiltinLintDiag::RedundantImport(spans, ident, import_span) => {
107107
for (span, is_imported) in spans {
108108
let introduced = if is_imported { "imported" } else { "defined" };
109-
diag.span_label(span, format!("the item `{ident}` is already {introduced} here"));
109+
let span_msg = if span.is_dummy() { "by prelude" } else { "here" };
110+
diag.span_label(
111+
span,
112+
format!("the item `{ident}` is already {introduced} {span_msg}"),
113+
);
110114
}
115+
diag.span_suggestion(
116+
import_span,
117+
"remove this import",
118+
"",
119+
Applicability::MachineApplicable,
120+
);
111121
}
112122
BuiltinLintDiag::DeprecatedMacro(suggestion, span) => {
113123
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 ImportVisitor {
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 ImportVisitor {
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 = ImportVisitor {
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
@@ -1304,7 +1304,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13041304
None
13051305
}
13061306

1307-
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) {
1307+
pub(crate) fn check_for_redundant_imports(
1308+
&mut self,
1309+
import: Import<'a>,
1310+
) -> Option<Vec<(Span, bool)>> {
13081311
// This function is only called for single imports.
13091312
let ImportKind::Single {
13101313
source, target, ref source_bindings, ref target_bindings, id, ..
@@ -1315,12 +1318,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13151318

13161319
// Skip if the import is of the form `use source as target` and source != target.
13171320
if source != target {
1318-
return;
1321+
return None;
13191322
}
13201323

13211324
// Skip if the import was produced by a macro.
13221325
if import.parent_scope.expansion != LocalExpnId::ROOT {
1323-
return;
1326+
return None;
13241327
}
13251328

13261329
// Skip if we are inside a named module (in contrast to an anonymous
@@ -1330,13 +1333,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13301333
if import.used.get() == Some(Used::Other)
13311334
|| self.effective_visibilities.is_exported(self.local_def_id(id))
13321335
{
1333-
return;
1336+
return None;
13341337
}
13351338

13361339
let mut is_redundant = true;
1337-
13381340
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
1339-
13401341
self.per_ns(|this, ns| {
13411342
if is_redundant && let Ok(binding) = source_bindings[ns].get() {
13421343
if binding.res() == Res::Err {
@@ -1368,14 +1369,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13681369
let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
13691370
redundant_spans.sort();
13701371
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-
);
1372+
return Some(redundant_spans);
13781373
}
1374+
None
13791375
}
13801376

13811377
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-prelude-rust-2015.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ warning: the item `Some` is imported redundantly
22
--> $DIR/use-redundant-prelude-rust-2015.rs:5:5
33
|
44
LL | use std::option::Option::Some;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ----^^^^^^^^^^^^^^^^^^^^^^^^^- help: remove this import
66
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
77
|
88
= note: the item `Some` is already defined here
@@ -17,7 +17,7 @@ warning: the item `None` is imported redundantly
1717
--> $DIR/use-redundant-prelude-rust-2015.rs:6:5
1818
|
1919
LL | use std::option::Option::None;
20-
| ^^^^^^^^^^^^^^^^^^^^^^^^^
20+
| ----^^^^^^^^^^^^^^^^^^^^^^^^^- help: remove this import
2121
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
2222
|
2323
= note: the item `None` is already defined here
@@ -26,7 +26,7 @@ warning: the item `Ok` is imported redundantly
2626
--> $DIR/use-redundant-prelude-rust-2015.rs:8:5
2727
|
2828
LL | use std::result::Result::Ok;
29-
| ^^^^^^^^^^^^^^^^^^^^^^^
29+
| ----^^^^^^^^^^^^^^^^^^^^^^^- help: remove this import
3030
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
3131
|
3232
= note: the item `Ok` is already defined here
@@ -35,7 +35,7 @@ warning: the item `Err` is imported redundantly
3535
--> $DIR/use-redundant-prelude-rust-2015.rs:9:5
3636
|
3737
LL | use std::result::Result::Err;
38-
| ^^^^^^^^^^^^^^^^^^^^^^^^
38+
| ----^^^^^^^^^^^^^^^^^^^^^^^^- help: remove this import
3939
--> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
4040
|
4141
= note: the item `Err` is already defined here

0 commit comments

Comments
 (0)