Skip to content

Commit ba20a86

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 8364a6f commit ba20a86

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
@@ -1463,7 +1463,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14631463
fn resolve_item_in_lexical_scope(&mut self,
14641464
module_: Rc<Module>,
14651465
name: Name,
1466-
namespace: Namespace)
1466+
namespace: Namespace,
1467+
record_used: bool)
14671468
-> ResolveResult<(Target, bool)> {
14681469
debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
14691470
name,
@@ -1503,10 +1504,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15031504
debug!("(resolving item in lexical scope) using import resolution");
15041505
// track used imports and extern crates as well
15051506
let id = import_resolution[namespace].id;
1506-
self.used_imports.insert((id, namespace));
1507-
self.record_import_use(id, name);
1508-
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
1509-
self.used_crates.insert(kid);
1507+
if record_used {
1508+
self.used_imports.insert((id, namespace));
1509+
self.record_import_use(id, name);
1510+
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
1511+
self.used_crates.insert(kid);
1512+
}
15101513
}
15111514
return Success((target, false));
15121515
}
@@ -1583,7 +1586,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15831586
-> ResolveResult<Rc<Module>> {
15841587
// If this module is an anonymous module, resolve the item in the
15851588
// lexical scope. Otherwise, resolve the item from the crate root.
1586-
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS);
1589+
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true);
15871590
match resolve_result {
15881591
Success((target, _)) => {
15891592
if let Some(module_def) = target.binding.module() {
@@ -2791,7 +2794,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
27912794
span: Span)
27922795
-> BareIdentifierPatternResolution {
27932796
let module = self.current_module.clone();
2794-
match self.resolve_item_in_lexical_scope(module, name, ValueNS) {
2797+
match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
27952798
Success((target, _)) => {
27962799
debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
27972800
name,
@@ -2899,17 +2902,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
28992902
}
29002903

29012904
// Try to find a path to an item in a module.
2902-
let unqualified_def = self.resolve_identifier(segments.last().unwrap().identifier,
2903-
namespace,
2904-
check_ribs);
2905-
2905+
let last_ident = segments.last().unwrap().identifier;
29062906
if segments.len() <= 1 {
2907+
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, true);
29072908
return unqualified_def.and_then(|def| self.adjust_local_def(def, span))
29082909
.map(|def| {
29092910
PathResolution::new(def, LastMod(AllPublic), path_depth)
29102911
});
29112912
}
29122913

2914+
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, false);
29132915
let def = self.resolve_module_relative_path(span, segments, namespace);
29142916
match (def, unqualified_def) {
29152917
(Some((ref d, _)), Some(ref ud)) if *d == ud.def => {
@@ -2929,7 +2931,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29292931
fn resolve_identifier(&mut self,
29302932
identifier: hir::Ident,
29312933
namespace: Namespace,
2932-
check_ribs: bool)
2934+
check_ribs: bool,
2935+
record_used: bool)
29332936
-> Option<LocalDef> {
29342937
// First, check to see whether the name is a primitive type.
29352938
if namespace == TypeNS {
@@ -2946,7 +2949,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29462949
}
29472950
}
29482951

2949-
self.resolve_item_by_name_in_lexical_scope(identifier.unhygienic_name, namespace)
2952+
let name = identifier.unhygienic_name;
2953+
self.resolve_item_by_name_in_lexical_scope(name, namespace, record_used)
29502954
.map(LocalDef::from_def)
29512955
}
29522956

@@ -3197,11 +3201,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
31973201

31983202
fn resolve_item_by_name_in_lexical_scope(&mut self,
31993203
name: Name,
3200-
namespace: Namespace)
3204+
namespace: Namespace,
3205+
record_used: bool)
32013206
-> Option<Def> {
32023207
// Check the items.
32033208
let module = self.current_module.clone();
3204-
match self.resolve_item_in_lexical_scope(module, name, namespace) {
3209+
match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
32053210
Success((target, _)) => {
32063211
match target.binding.def() {
32073212
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)