Skip to content

Commit 207bfee

Browse files
committed
rustc: Add self/super hint for extern crate resolve errors.
1 parent db29814 commit 207bfee

File tree

4 files changed

+92
-30
lines changed

4 files changed

+92
-30
lines changed

src/librustc/middle/resolve.rs

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,26 +1485,21 @@ impl<'a> Resolver<'a> {
14851485

14861486
ViewItemExternCrate(name, _, node_id) => {
14871487
// n.b. we don't need to look at the path option here, because cstore already did
1488-
match self.session.cstore.find_extern_mod_stmt_cnum(node_id) {
1489-
Some(crate_id) => {
1490-
let def_id = DefId { krate: crate_id, node: 0 };
1491-
self.external_exports.insert(def_id);
1492-
let parent_link = ModuleParentLink
1493-
(parent.module().downgrade(), name);
1494-
let external_module = Rc::new(Module::new(parent_link,
1495-
Some(def_id),
1496-
NormalModuleKind,
1497-
false,
1498-
true));
1499-
1500-
parent.module().external_module_children
1501-
.borrow_mut().insert(name.name,
1502-
external_module.clone());
1503-
1504-
self.build_reduced_graph_for_external_crate(
1505-
external_module);
1506-
}
1507-
None => {} // Ignore.
1488+
for &crate_id in self.session.cstore.find_extern_mod_stmt_cnum(node_id).iter() {
1489+
let def_id = DefId { krate: crate_id, node: 0 };
1490+
self.external_exports.insert(def_id);
1491+
let parent_link = ModuleParentLink(parent.module().downgrade(), name);
1492+
let external_module = Rc::new(Module::new(parent_link,
1493+
Some(def_id),
1494+
NormalModuleKind,
1495+
false,
1496+
true));
1497+
debug!("(build reduced graph for item) found extern `{}`",
1498+
self.module_to_str(&*external_module));
1499+
parent.module().external_module_children.borrow_mut()
1500+
.insert(name.name,
1501+
external_module.clone());
1502+
self.build_reduced_graph_for_external_crate(external_module);
15081503
}
15091504
}
15101505
}
@@ -1997,7 +1992,9 @@ impl<'a> Resolver<'a> {
19971992
fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
19981993
debug!("(resolving imports for module subtree) resolving {}",
19991994
self.module_to_str(&*module_));
1995+
let orig_module = replace(&mut self.current_module, module_.clone());
20001996
self.resolve_imports_for_module(module_.clone());
1997+
self.current_module = orig_module;
20011998

20021999
self.populate_module_if_necessary(&module_);
20032000
for (_, child_node) in module_.children.borrow().iter() {
@@ -2611,6 +2608,22 @@ impl<'a> Resolver<'a> {
26112608
name_search_type: NameSearchType,
26122609
lp: LastPrivate)
26132610
-> ResolveResult<(Rc<Module>, LastPrivate)> {
2611+
fn search_parent_externals(needle: Name, module: &Rc<Module>)
2612+
-> Option<Rc<Module>> {
2613+
module.external_module_children.borrow()
2614+
.find_copy(&needle)
2615+
.map(|_| module.clone())
2616+
.or_else(|| {
2617+
match module.parent_link.clone() {
2618+
ModuleParentLink(parent, _) => {
2619+
search_parent_externals(needle,
2620+
&parent.upgrade().unwrap())
2621+
}
2622+
_ => None
2623+
}
2624+
})
2625+
}
2626+
26142627
let mut search_module = module_;
26152628
let mut index = index;
26162629
let module_path_len = module_path.len();
@@ -2635,11 +2648,28 @@ impl<'a> Resolver<'a> {
26352648
hi: span.lo + Pos::from_uint(segment_name.get().len()),
26362649
expn_info: span.expn_info,
26372650
};
2638-
self.resolve_error(span,
2639-
format!("unresolved import. maybe \
2640-
a missing `extern crate \
2641-
{}`?",
2642-
segment_name).as_slice());
2651+
2652+
match search_parent_externals(name.name, &self.current_module) {
2653+
Some(module) => {
2654+
let path_str = self.idents_to_str(module_path);
2655+
let target_mod_str = self.module_to_str(&*module);
2656+
let current_mod_str = self.module_to_str(&*self.current_module);
2657+
2658+
let prefix = if target_mod_str == current_mod_str {
2659+
"self::".to_string()
2660+
} else {
2661+
format!("{}::", target_mod_str)
2662+
};
2663+
2664+
self.resolve_error(span, format!("unresolved import. Did you mean \
2665+
`{}{}`?",
2666+
prefix, path_str).as_slice());
2667+
},
2668+
None => self.resolve_error(span, format!("unresolved import. Maybe a \
2669+
missing `extern crate {}`?",
2670+
segment_name).as_slice()),
2671+
}
2672+
26432673
return Failed;
26442674
}
26452675
self.resolve_error(span,
@@ -5480,7 +5510,7 @@ impl<'a> Resolver<'a> {
54805510
//
54815511

54825512
/// A somewhat inefficient routine to obtain the name of a module.
5483-
fn module_to_str(&mut self, module: &Module) -> String {
5513+
fn module_to_str(&self, module: &Module) -> String {
54845514
let mut idents = Vec::new();
54855515

54865516
fn collect_mod(idents: &mut Vec<ast::Ident>, module: &Module) {

src/test/compile-fail/issue-1697.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -12,7 +12,7 @@
1212

1313
#![feature(globs)]
1414

15-
use unresolved::*; //~ ERROR unresolved import. maybe a missing
15+
use unresolved::*; //~ ERROR unresolved import. Maybe a missing
1616
//~^ ERROR failed to resolve import
1717

1818
fn main() {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
mod a {
12+
extern crate collections;
13+
use collections::HashMap;
14+
//~^ ERROR unresolved import. Did you mean `self::collections`?
15+
//~^^ ERROR failed to resolve import `collections::HashMap`
16+
17+
mod b {
18+
use collections::HashMap;
19+
//~^ ERROR unresolved import. Did you mean `a::collections`?
20+
//~^^ ERROR failed to resolve import `collections::HashMap`
21+
mod c {
22+
use collections::HashMap;
23+
//~^ ERROR unresolved import. Did you mean `a::collections`?
24+
//~^^ ERROR failed to resolve import `collections::HashMap`
25+
mod d {
26+
use collections::HashMap;
27+
//~^ ERROR unresolved import. Did you mean `a::collections`
28+
//~^^ ERROR failed to resolve import `collections::HashMap`
29+
}
30+
}
31+
}
32+
}

src/test/compile-fail/unresolved-import.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use foo::bar; //~ ERROR unresolved import. maybe a missing `extern crate foo`?
11+
use foo::bar; //~ ERROR unresolved import. Maybe a missing `extern crate foo`?
1212
//~^ ERROR failed to resolve import `foo::bar`
1313
use x = bar::baz; //~ ERROR unresolved import: there is no `baz` in `bar`
1414
//~^ ERROR failed to resolve import `bar::baz`

0 commit comments

Comments
 (0)