Skip to content

Commit 83dde14

Browse files
committed
rustc_resolve: fix a bug in which unused imports can get wrongly marked as used when checking for unused qualifications in resolve_path (fixes #30078)
1 parent 9a2549e commit 83dde14

File tree

3 files changed

+25
-16
lines changed

3 files changed

+25
-16
lines changed

src/librustc_resolve/lib.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -1462,7 +1462,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14621462
fn resolve_item_in_lexical_scope(&mut self,
14631463
module_: Rc<Module>,
14641464
name: Name,
1465-
namespace: Namespace)
1465+
namespace: Namespace,
1466+
record_used: bool)
14661467
-> ResolveResult<(Target, bool)> {
14671468
debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
14681469
name,
@@ -1502,10 +1503,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15021503
debug!("(resolving item in lexical scope) using import resolution");
15031504
// track used imports and extern crates as well
15041505
let id = import_resolution[namespace].id;
1505-
self.used_imports.insert((id, namespace));
1506-
self.record_import_use(id, name);
1507-
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
1508-
self.used_crates.insert(kid);
1506+
if record_used {
1507+
self.used_imports.insert((id, namespace));
1508+
self.record_import_use(id, name);
1509+
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
1510+
self.used_crates.insert(kid);
1511+
}
15091512
}
15101513
return Success((target, false));
15111514
}
@@ -1582,7 +1585,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15821585
-> ResolveResult<Rc<Module>> {
15831586
// If this module is an anonymous module, resolve the item in the
15841587
// lexical scope. Otherwise, resolve the item from the crate root.
1585-
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS);
1588+
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true);
15861589
match resolve_result {
15871590
Success((target, _)) => {
15881591
if let Some(module_def) = target.binding.module() {
@@ -2776,7 +2779,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
27762779
span: Span)
27772780
-> BareIdentifierPatternResolution {
27782781
let module = self.current_module.clone();
2779-
match self.resolve_item_in_lexical_scope(module, name, ValueNS) {
2782+
match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
27802783
Success((target, _)) => {
27812784
debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
27822785
name,
@@ -2884,17 +2887,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28842887
}
28852888

28862889
// Try to find a path to an item in a module.
2887-
let unqualified_def = self.resolve_identifier(segments.last().unwrap().identifier,
2888-
namespace,
2889-
check_ribs);
2890-
2890+
let last_ident = segments.last().unwrap().identifier;
28912891
if segments.len() <= 1 {
2892+
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, true);
28922893
return unqualified_def.and_then(|def| self.adjust_local_def(def, span))
28932894
.map(|def| {
28942895
PathResolution::new(def, LastMod(AllPublic), path_depth)
28952896
});
28962897
}
28972898

2899+
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, false);
28982900
let def = self.resolve_module_relative_path(span, segments, namespace);
28992901
match (def, unqualified_def) {
29002902
(Some((ref d, _)), Some(ref ud)) if *d == ud.def => {
@@ -2914,7 +2916,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29142916
fn resolve_identifier(&mut self,
29152917
identifier: hir::Ident,
29162918
namespace: Namespace,
2917-
check_ribs: bool)
2919+
check_ribs: bool,
2920+
record_used: bool)
29182921
-> Option<LocalDef> {
29192922
// First, check to see whether the name is a primitive type.
29202923
if namespace == TypeNS {
@@ -2931,7 +2934,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29312934
}
29322935
}
29332936

2934-
self.resolve_item_by_name_in_lexical_scope(identifier.unhygienic_name, namespace)
2937+
let name = identifier.unhygienic_name;
2938+
self.resolve_item_by_name_in_lexical_scope(name, namespace, record_used)
29352939
.map(LocalDef::from_def)
29362940
}
29372941

@@ -3182,11 +3186,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31823186

31833187
fn resolve_item_by_name_in_lexical_scope(&mut self,
31843188
name: Name,
3185-
namespace: Namespace)
3189+
namespace: Namespace,
3190+
record_used: bool)
31863191
-> Option<Def> {
31873192
// Check the items.
31883193
let module = self.current_module.clone();
3189-
match self.resolve_item_in_lexical_scope(module, name, namespace) {
3194+
match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
31903195
Success((target, _)) => {
31913196
match target.binding.def() {
31923197
None => {

src/test/compile-fail/lint-qualification.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ mod foo {
1717
fn main() {
1818
use foo::bar;
1919
foo::bar(); //~ ERROR: unnecessary qualification
20+
bar();
2021
}

src/test/compile-fail/lint-unused-imports.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,14 @@ mod foo {
5050
mod bar {
5151
// Don't ignore on 'pub use' because we're not sure if it's used or not
5252
pub use std::cmp::PartialEq;
53+
pub struct Square;
5354

5455
pub mod c {
5556
use foo::Point;
5657
use foo::Square; //~ ERROR unused import
57-
pub fn cc(p: Point) -> isize { return 2 * (p.x + p.y); }
58+
pub fn cc(_p: Point) -> super::Square {
59+
super::Square
60+
}
5861
}
5962

6063
#[allow(unused_imports)]

0 commit comments

Comments
 (0)