Skip to content

Commit 4f5616e

Browse files
committed
Avoid cascading name resolution errors caused by an ambiguous module.
1 parent 32a0cfe commit 4f5616e

File tree

3 files changed

+45
-30
lines changed

3 files changed

+45
-30
lines changed

src/librustc_resolve/lib.rs

+39-29
Original file line numberDiff line numberDiff line change
@@ -749,10 +749,6 @@ impl<'a> LexicalScopeBinding<'a> {
749749
_ => None,
750750
}
751751
}
752-
753-
fn module(self) -> Option<Module<'a>> {
754-
self.item().and_then(NameBinding::module)
755-
}
756752
}
757753

758754
/// The link from a module up to its nearest parent node.
@@ -884,12 +880,13 @@ enum NameBindingKind<'a> {
884880
struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
885881

886882
impl<'a> NameBinding<'a> {
887-
fn module(&self) -> Option<Module<'a>> {
883+
fn module(&self) -> Result<Module<'a>, bool /* true if an error has already been reported */> {
888884
match self.kind {
889-
NameBindingKind::Module(module) => Some(module),
890-
NameBindingKind::Def(_) => None,
885+
NameBindingKind::Module(module) => Ok(module),
891886
NameBindingKind::Import { binding, .. } => binding.module(),
892-
NameBindingKind::Ambiguity { .. } => None,
887+
NameBindingKind::Def(Def::Err) => Err(true),
888+
NameBindingKind::Def(_) => Err(false),
889+
NameBindingKind::Ambiguity { .. } => Err(false),
893890
}
894891
}
895892

@@ -915,7 +912,7 @@ impl<'a> NameBinding<'a> {
915912
}
916913

917914
fn is_extern_crate(&self) -> bool {
918-
self.module().and_then(|module| module.extern_crate_id).is_some()
915+
self.module().ok().and_then(|module| module.extern_crate_id).is_some()
919916
}
920917

921918
fn is_import(&self) -> bool {
@@ -1269,7 +1266,7 @@ impl<'a> Resolver<'a> {
12691266
fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
12701267
-> bool /* true if an error was reported */ {
12711268
// track extern crates for unused_extern_crate lint
1272-
if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) {
1269+
if let Some(DefId { krate, .. }) = binding.module().ok().and_then(ModuleS::def_id) {
12731270
self.used_crates.insert(krate);
12741271
}
12751272

@@ -1292,6 +1289,18 @@ impl<'a> Resolver<'a> {
12921289
}
12931290
}
12941291

1292+
fn expect_module(&mut self, name: Name, binding: &'a NameBinding<'a>, span: Option<Span>)
1293+
-> ResolveResult<Module<'a>> {
1294+
match binding.module() {
1295+
Ok(module) => Success(module),
1296+
Err(true) => Failed(None),
1297+
Err(false) => {
1298+
let msg = format!("Not a module `{}`", name);
1299+
Failed(span.map(|span| (span, msg)))
1300+
}
1301+
}
1302+
}
1303+
12951304
/// Resolves the given module path from the given root `search_module`.
12961305
fn resolve_module_path_from_root(&mut self,
12971306
mut search_module: Module<'a>,
@@ -1357,11 +1366,9 @@ impl<'a> Resolver<'a> {
13571366
Success(binding) => {
13581367
// Check to see whether there are type bindings, and, if
13591368
// so, whether there is a module within.
1360-
if let Some(module_def) = binding.module() {
1361-
search_module = module_def;
1362-
} else {
1363-
let msg = format!("Not a module `{}`", name);
1364-
return Failed(span.map(|span| (span, msg)));
1369+
match self.expect_module(name, binding, span) {
1370+
Success(module) => search_module = module,
1371+
result @ _ => return result,
13651372
}
13661373
}
13671374
}
@@ -1414,17 +1421,20 @@ impl<'a> Resolver<'a> {
14141421
// first component of the path in the current lexical
14151422
// scope and then proceed to resolve below that.
14161423
let ident = ast::Ident::with_empty_ctxt(module_path[0]);
1417-
match self.resolve_ident_in_lexical_scope(ident, TypeNS, span)
1418-
.and_then(LexicalScopeBinding::module) {
1419-
None => {
1420-
let msg =
1421-
format!("Use of undeclared type or module `{}`", ident.name);
1422-
return Failed(span.map(|span| (span, msg)));
1423-
}
1424-
Some(containing_module) => {
1425-
search_module = containing_module;
1426-
start_index = 1;
1424+
let lexical_binding =
1425+
self.resolve_ident_in_lexical_scope(ident, TypeNS, span);
1426+
if let Some(binding) = lexical_binding.and_then(LexicalScopeBinding::item) {
1427+
match self.expect_module(ident.name, binding, span) {
1428+
Success(containing_module) => {
1429+
search_module = containing_module;
1430+
start_index = 1;
1431+
}
1432+
result @ _ => return result,
14271433
}
1434+
} else {
1435+
let msg =
1436+
format!("Use of undeclared type or module `{}`", ident.name);
1437+
return Failed(span.map(|span| (span, msg)));
14281438
}
14291439
}
14301440
}
@@ -3202,7 +3212,7 @@ impl<'a> Resolver<'a> {
32023212
}
32033213

32043214
// collect submodules to explore
3205-
if let Some(module) = name_binding.module() {
3215+
if let Ok(module) = name_binding.module() {
32063216
// form the path
32073217
let path_segments = match module.parent_link {
32083218
NoParentLink => path_segments.clone(),
@@ -3341,9 +3351,9 @@ impl<'a> Resolver<'a> {
33413351
let msg = {
33423352
let kind = match (ns, old_binding.module()) {
33433353
(ValueNS, _) => "a value",
3344-
(TypeNS, Some(module)) if module.extern_crate_id.is_some() => "an extern crate",
3345-
(TypeNS, Some(module)) if module.is_normal() => "a module",
3346-
(TypeNS, Some(module)) if module.is_trait() => "a trait",
3354+
(TypeNS, Ok(module)) if module.extern_crate_id.is_some() => "an extern crate",
3355+
(TypeNS, Ok(module)) if module.is_normal() => "a module",
3356+
(TypeNS, Ok(module)) if module.is_trait() => "a trait",
33473357
(TypeNS, _) => "a type",
33483358
};
33493359
format!("{} named `{}` has already been {} in this {}",

src/librustc_resolve/resolve_imports.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
460460
errors = true;
461461
let (span, help) = match err {
462462
Some((span, msg)) => (span, msg),
463-
None => (import.span, String::new()),
463+
None => continue,
464464
};
465465

466466
// If the error is a single failed import then create a "fake" import

src/test/compile-fail/imports/duplicate.rs

+5
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ mod ambiguous_module_errors {
5656
pub mod m2 { pub use super::m2 as foo; }
5757

5858
use self::m1::*; //~ NOTE
59+
//~| NOTE
5960
use self::m2::*; //~ NOTE
61+
//~| NOTE
62+
63+
use self::foo::bar; //~ ERROR `foo` is ambiguous
64+
//~| NOTE
6065

6166
fn f() {
6267
foo::bar(); //~ ERROR `foo` is ambiguous

0 commit comments

Comments
 (0)