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)

This commit is contained in:
Jeffrey Seyfried 2015-12-12 03:30:53 +00:00
parent 8364a6feef
commit ba20a862d4
3 changed files with 25 additions and 16 deletions

View file

@ -1463,7 +1463,8 @@ fn resolve_module_path(&mut self,
fn resolve_item_in_lexical_scope(&mut self,
module_: Rc<Module>,
name: Name,
namespace: Namespace)
namespace: Namespace,
record_used: bool)
-> ResolveResult<(Target, bool)> {
debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`",
name,
@ -1503,10 +1504,12 @@ fn resolve_item_in_lexical_scope(&mut self,
debug!("(resolving item in lexical scope) using import resolution");
// track used imports and extern crates as well
let id = import_resolution[namespace].id;
self.used_imports.insert((id, namespace));
self.record_import_use(id, name);
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
self.used_crates.insert(kid);
if record_used {
self.used_imports.insert((id, namespace));
self.record_import_use(id, name);
if let Some(DefId{krate: kid, ..}) = target.target_module.def_id() {
self.used_crates.insert(kid);
}
}
return Success((target, false));
}
@ -1583,7 +1586,7 @@ fn resolve_module_in_lexical_scope(&mut self,
-> ResolveResult<Rc<Module>> {
// If this module is an anonymous module, resolve the item in the
// lexical scope. Otherwise, resolve the item from the crate root.
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS);
let resolve_result = self.resolve_item_in_lexical_scope(module_, name, TypeNS, true);
match resolve_result {
Success((target, _)) => {
if let Some(module_def) = target.binding.module() {
@ -2791,7 +2794,7 @@ fn resolve_bare_identifier_pattern(&mut self,
span: Span)
-> BareIdentifierPatternResolution {
let module = self.current_module.clone();
match self.resolve_item_in_lexical_scope(module, name, ValueNS) {
match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) {
Success((target, _)) => {
debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}",
name,
@ -2899,17 +2902,16 @@ pub fn resolve_path(&mut self,
}
// Try to find a path to an item in a module.
let unqualified_def = self.resolve_identifier(segments.last().unwrap().identifier,
namespace,
check_ribs);
let last_ident = segments.last().unwrap().identifier;
if segments.len() <= 1 {
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, true);
return unqualified_def.and_then(|def| self.adjust_local_def(def, span))
.map(|def| {
PathResolution::new(def, LastMod(AllPublic), path_depth)
});
}
let unqualified_def = self.resolve_identifier(last_ident, namespace, check_ribs, false);
let def = self.resolve_module_relative_path(span, segments, namespace);
match (def, unqualified_def) {
(Some((ref d, _)), Some(ref ud)) if *d == ud.def => {
@ -2929,7 +2931,8 @@ pub fn resolve_path(&mut self,
fn resolve_identifier(&mut self,
identifier: hir::Ident,
namespace: Namespace,
check_ribs: bool)
check_ribs: bool,
record_used: bool)
-> Option<LocalDef> {
// First, check to see whether the name is a primitive type.
if namespace == TypeNS {
@ -2946,7 +2949,8 @@ fn resolve_identifier(&mut self,
}
}
self.resolve_item_by_name_in_lexical_scope(identifier.unhygienic_name, namespace)
let name = identifier.unhygienic_name;
self.resolve_item_by_name_in_lexical_scope(name, namespace, record_used)
.map(LocalDef::from_def)
}
@ -3197,11 +3201,12 @@ fn resolve_identifier_in_local_ribs(&mut self,
fn resolve_item_by_name_in_lexical_scope(&mut self,
name: Name,
namespace: Namespace)
namespace: Namespace,
record_used: bool)
-> Option<Def> {
// Check the items.
let module = self.current_module.clone();
match self.resolve_item_in_lexical_scope(module, name, namespace) {
match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) {
Success((target, _)) => {
match target.binding.def() {
None => {

View file

@ -17,4 +17,5 @@ pub fn bar() {}
fn main() {
use foo::bar;
foo::bar(); //~ ERROR: unnecessary qualification
bar();
}

View file

@ -50,11 +50,14 @@ pub struct Square{pub p: Point, pub h: usize, pub w: usize}
mod bar {
// Don't ignore on 'pub use' because we're not sure if it's used or not
pub use std::cmp::PartialEq;
pub struct Square;
pub mod c {
use foo::Point;
use foo::Square; //~ ERROR unused import
pub fn cc(p: Point) -> isize { return 2 * (p.x + p.y); }
pub fn cc(_p: Point) -> super::Square {
super::Square
}
}
#[allow(unused_imports)]