Skip to content

Commit 35d06f9

Browse files
committed
Auto merge of rust-lang#109599 - notriddle:notriddle/use-redundant-glob, r=petrochenkov
diagnostics: account for glob shadowing when linting redundant imports Fixes rust-lang#92904
2 parents bd991d9 + 000e94e commit 35d06f9

10 files changed

+142
-14
lines changed

compiler/rustc_resolve/src/ident.rs

+21-14
Original file line numberDiff line numberDiff line change
@@ -869,17 +869,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
869869
let resolution =
870870
self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
871871

872-
if let Some(Finalize { path_span, report_private, .. }) = finalize {
873-
// If the primary binding is unusable, search further and return the shadowed glob
874-
// binding if it exists. What we really want here is having two separate scopes in
875-
// a module - one for non-globs and one for globs, but until that's done use this
876-
// hack to avoid inconsistent resolution ICEs during import validation.
877-
let binding = [resolution.binding, resolution.shadowed_glob].into_iter().find_map(
878-
|binding| match (binding, ignore_binding) {
872+
// If the primary binding is unusable, search further and return the shadowed glob
873+
// binding if it exists. What we really want here is having two separate scopes in
874+
// a module - one for non-globs and one for globs, but until that's done use this
875+
// hack to avoid inconsistent resolution ICEs during import validation.
876+
let binding =
877+
[resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| {
878+
match (binding, ignore_binding) {
879879
(Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
880880
_ => binding,
881-
},
882-
);
881+
}
882+
});
883+
884+
if let Some(Finalize { path_span, report_private, .. }) = finalize {
883885
let Some(binding) = binding else {
884886
return Err((Determined, Weak::No));
885887
};
@@ -927,15 +929,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
927929
}
928930

929931
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
930-
if let Some(ignored) = ignore_binding && ptr::eq(binding, ignored) {
931-
return Err((Determined, Weak::No));
932-
}
933932
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
934933
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
935934
};
936935

937936
// Items and single imports are not shadowable, if we have one, then it's determined.
938-
if let Some(binding) = resolution.binding {
937+
if let Some(binding) = binding {
939938
if !binding.is_glob_import() {
940939
return check_usable(self, binding);
941940
}
@@ -952,6 +951,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
952951
if !self.is_accessible_from(import_vis, parent_scope.module) {
953952
continue;
954953
}
954+
if let Some(ignored) = ignore_binding &&
955+
let NameBindingKind::Import { import, .. } = ignored.kind &&
956+
ptr::eq(import, &**single_import) {
957+
// Ignore not just the binding itself, but if it has a shadowed_glob,
958+
// ignore that, too, because this loop is supposed to only process
959+
// named imports.
960+
continue;
961+
}
955962
let Some(module) = single_import.imported_module.get() else {
956963
return Err((Undetermined, Weak::No));
957964
};
@@ -989,7 +996,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
989996
// and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
990997
// shadowing is enabled, see `macro_expanded_macro_export_errors`).
991998
let unexpanded_macros = !module.unexpanded_invocations.borrow().is_empty();
992-
if let Some(binding) = resolution.binding {
999+
if let Some(binding) = binding {
9931000
if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
9941001
return check_usable(self, binding);
9951002
} else {
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// check-pass
2+
3+
pub struct Foo(bar::Bar);
4+
5+
pub mod bar {
6+
pub struct Foo(pub Bar);
7+
pub struct Bar(pub char);
8+
}
9+
10+
pub fn warning() -> Foo {
11+
use bar::*;
12+
#[deny(unused_imports)]
13+
use self::Foo; // no error
14+
Foo(Bar('a'))
15+
}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
#![warn(unused_imports)]
3+
4+
pub mod bar {
5+
pub struct Foo(pub Bar);
6+
pub struct Bar(pub char);
7+
}
8+
9+
use bar::*;
10+
11+
pub fn warning() -> Foo {
12+
use bar::Foo; //~ WARNING imported redundantly
13+
Foo(Bar('a'))
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
warning: the item `Foo` is imported redundantly
2+
--> $DIR/use-redundant-glob-parent.rs:12:9
3+
|
4+
LL | use bar::*;
5+
| ------ the item `Foo` is already imported here
6+
...
7+
LL | use bar::Foo;
8+
| ^^^^^^^^
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/use-redundant-glob-parent.rs:2:9
12+
|
13+
LL | #![warn(unused_imports)]
14+
| ^^^^^^^^^^^^^^
15+
16+
warning: 1 warning emitted
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
#![warn(unused_imports)]
3+
4+
pub mod bar {
5+
pub struct Foo(pub Bar);
6+
pub struct Bar(pub char);
7+
}
8+
9+
pub fn warning() -> bar::Foo {
10+
use bar::*;
11+
use bar::Foo; //~ WARNING imported redundantly
12+
Foo(Bar('a'))
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
warning: the item `Foo` is imported redundantly
2+
--> $DIR/use-redundant-glob.rs:11:9
3+
|
4+
LL | use bar::*;
5+
| ------ the item `Foo` is already imported here
6+
LL | use bar::Foo;
7+
| ^^^^^^^^
8+
|
9+
note: the lint level is defined here
10+
--> $DIR/use-redundant-glob.rs:2:9
11+
|
12+
LL | #![warn(unused_imports)]
13+
| ^^^^^^^^^^^^^^
14+
15+
warning: 1 warning emitted
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// check-pass
2+
#![allow(nonstandard_style)]
3+
4+
pub mod bar {
5+
pub struct Foo { pub bar: Bar }
6+
pub struct Bar(pub char);
7+
}
8+
9+
pub mod x {
10+
use crate::bar;
11+
pub const Foo: bar::Bar = bar::Bar('a');
12+
}
13+
14+
pub fn warning() -> bar::Foo {
15+
#![deny(unused_imports)] // no error
16+
use bar::*;
17+
use x::Foo;
18+
Foo { bar: Foo }
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
3+
pub mod bar {
4+
pub struct Foo(pub Bar);
5+
pub struct Bar(pub char);
6+
}
7+
8+
pub mod x {
9+
pub struct Foo(pub crate::bar::Bar);
10+
}
11+
12+
pub fn warning() -> x::Foo {
13+
use bar::*;
14+
#[deny(unused_imports)]
15+
use x::Foo; // no error
16+
Foo(Bar('a'))
17+
}
18+
19+
fn main() {}

0 commit comments

Comments
 (0)