From 207bfee2140857ac5161686db97cef90f0e38907 Mon Sep 17 00:00:00 2001 From: Kevin Butler Date: Wed, 4 Jun 2014 23:55:10 +0100 Subject: [PATCH] rustc: Add self/super hint for extern crate resolve errors. --- src/librustc/middle/resolve.rs | 82 +++++++++++++------ src/test/compile-fail/issue-1697.rs | 4 +- .../compile-fail/resolve_self_super_hint.rs | 32 ++++++++ src/test/compile-fail/unresolved-import.rs | 4 +- 4 files changed, 92 insertions(+), 30 deletions(-) create mode 100644 src/test/compile-fail/resolve_self_super_hint.rs diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 53c09fcf283..7710ef8d733 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1485,26 +1485,21 @@ impl<'a> Resolver<'a> { ViewItemExternCrate(name, _, node_id) => { // n.b. we don't need to look at the path option here, because cstore already did - match self.session.cstore.find_extern_mod_stmt_cnum(node_id) { - Some(crate_id) => { - let def_id = DefId { krate: crate_id, node: 0 }; - self.external_exports.insert(def_id); - let parent_link = ModuleParentLink - (parent.module().downgrade(), name); - let external_module = Rc::new(Module::new(parent_link, - Some(def_id), - NormalModuleKind, - false, - true)); - - parent.module().external_module_children - .borrow_mut().insert(name.name, - external_module.clone()); - - self.build_reduced_graph_for_external_crate( - external_module); - } - None => {} // Ignore. + for &crate_id in self.session.cstore.find_extern_mod_stmt_cnum(node_id).iter() { + let def_id = DefId { krate: crate_id, node: 0 }; + self.external_exports.insert(def_id); + let parent_link = ModuleParentLink(parent.module().downgrade(), name); + let external_module = Rc::new(Module::new(parent_link, + Some(def_id), + NormalModuleKind, + false, + true)); + debug!("(build reduced graph for item) found extern `{}`", + self.module_to_str(&*external_module)); + parent.module().external_module_children.borrow_mut() + .insert(name.name, + external_module.clone()); + self.build_reduced_graph_for_external_crate(external_module); } } } @@ -1997,7 +1992,9 @@ impl<'a> Resolver<'a> { fn resolve_imports_for_module_subtree(&mut self, module_: Rc) { debug!("(resolving imports for module subtree) resolving {}", self.module_to_str(&*module_)); + let orig_module = replace(&mut self.current_module, module_.clone()); self.resolve_imports_for_module(module_.clone()); + self.current_module = orig_module; self.populate_module_if_necessary(&module_); for (_, child_node) in module_.children.borrow().iter() { @@ -2611,6 +2608,22 @@ impl<'a> Resolver<'a> { name_search_type: NameSearchType, lp: LastPrivate) -> ResolveResult<(Rc, LastPrivate)> { + fn search_parent_externals(needle: Name, module: &Rc) + -> Option> { + module.external_module_children.borrow() + .find_copy(&needle) + .map(|_| module.clone()) + .or_else(|| { + match module.parent_link.clone() { + ModuleParentLink(parent, _) => { + search_parent_externals(needle, + &parent.upgrade().unwrap()) + } + _ => None + } + }) + } + let mut search_module = module_; let mut index = index; let module_path_len = module_path.len(); @@ -2635,11 +2648,28 @@ impl<'a> Resolver<'a> { hi: span.lo + Pos::from_uint(segment_name.get().len()), expn_info: span.expn_info, }; - self.resolve_error(span, - format!("unresolved import. maybe \ - a missing `extern crate \ - {}`?", - segment_name).as_slice()); + + match search_parent_externals(name.name, &self.current_module) { + Some(module) => { + let path_str = self.idents_to_str(module_path); + let target_mod_str = self.module_to_str(&*module); + let current_mod_str = self.module_to_str(&*self.current_module); + + let prefix = if target_mod_str == current_mod_str { + "self::".to_string() + } else { + format!("{}::", target_mod_str) + }; + + self.resolve_error(span, format!("unresolved import. Did you mean \ + `{}{}`?", + prefix, path_str).as_slice()); + }, + None => self.resolve_error(span, format!("unresolved import. Maybe a \ + missing `extern crate {}`?", + segment_name).as_slice()), + } + return Failed; } self.resolve_error(span, @@ -5480,7 +5510,7 @@ impl<'a> Resolver<'a> { // /// A somewhat inefficient routine to obtain the name of a module. - fn module_to_str(&mut self, module: &Module) -> String { + fn module_to_str(&self, module: &Module) -> String { let mut idents = Vec::new(); fn collect_mod(idents: &mut Vec, module: &Module) { diff --git a/src/test/compile-fail/issue-1697.rs b/src/test/compile-fail/issue-1697.rs index f79a8fffd92..84ff07facee 100644 --- a/src/test/compile-fail/issue-1697.rs +++ b/src/test/compile-fail/issue-1697.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -12,7 +12,7 @@ #![feature(globs)] -use unresolved::*; //~ ERROR unresolved import. maybe a missing +use unresolved::*; //~ ERROR unresolved import. Maybe a missing //~^ ERROR failed to resolve import fn main() { diff --git a/src/test/compile-fail/resolve_self_super_hint.rs b/src/test/compile-fail/resolve_self_super_hint.rs new file mode 100644 index 00000000000..f900d3a74ed --- /dev/null +++ b/src/test/compile-fail/resolve_self_super_hint.rs @@ -0,0 +1,32 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod a { + extern crate collections; + use collections::HashMap; + //~^ ERROR unresolved import. Did you mean `self::collections`? + //~^^ ERROR failed to resolve import `collections::HashMap` + + mod b { + use collections::HashMap; +//~^ ERROR unresolved import. Did you mean `a::collections`? +//~^^ ERROR failed to resolve import `collections::HashMap` + mod c { + use collections::HashMap; +//~^ ERROR unresolved import. Did you mean `a::collections`? +//~^^ ERROR failed to resolve import `collections::HashMap` + mod d { + use collections::HashMap; +//~^ ERROR unresolved import. Did you mean `a::collections` +//~^^ ERROR failed to resolve import `collections::HashMap` + } + } + } +} diff --git a/src/test/compile-fail/unresolved-import.rs b/src/test/compile-fail/unresolved-import.rs index cb009163697..a614ed109d8 100644 --- a/src/test/compile-fail/unresolved-import.rs +++ b/src/test/compile-fail/unresolved-import.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use foo::bar; //~ ERROR unresolved import. maybe a missing `extern crate foo`? +use foo::bar; //~ ERROR unresolved import. Maybe a missing `extern crate foo`? //~^ ERROR failed to resolve import `foo::bar` use x = bar::baz; //~ ERROR unresolved import: there is no `baz` in `bar` //~^ ERROR failed to resolve import `bar::baz`