]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Add self/super hint for extern crate resolve errors.
authorKevin Butler <haqkrs@gmail.com>
Wed, 4 Jun 2014 22:55:10 +0000 (23:55 +0100)
committerKevin Butler <haqkrs@gmail.com>
Tue, 17 Jun 2014 21:08:56 +0000 (22:08 +0100)
src/librustc/middle/resolve.rs
src/test/compile-fail/issue-1697.rs
src/test/compile-fail/resolve_self_super_hint.rs [new file with mode: 0644]
src/test/compile-fail/unresolved-import.rs

index 53c09fcf283507af68fc20ec97de2cd1a32b873f..7710ef8d733b7d5a0c5f645696793b1486c632d7 100644 (file)
@@ -1485,26 +1485,21 @@ fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem,
 
             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 @@ fn resolve_imports(&mut self) {
     fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
         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 @@ fn resolve_module_path_from_root(&mut self,
                                      name_search_type: NameSearchType,
                                      lp: LastPrivate)
                                 -> ResolveResult<(Rc<Module>, LastPrivate)> {
+        fn search_parent_externals(needle: Name, module: &Rc<Module>)
+                                -> Option<Rc<Module>> {
+            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 @@ fn resolve_module_path_from_root(&mut self,
                             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 @@ fn finalize_import(&mut self, id: NodeId, span: Span) {
     //
 
     /// 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<ast::Ident>, module: &Module) {
index f79a8fffd922d8b1e83f6613489666cf89e7a4fd..84ff07facee5aa0c6c6b5be8827d9caf28d4e97c 100644 (file)
@@ -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 (file)
index 0000000..f900d3a
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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`
+            }
+        }
+    }
+}
index cb009163697f76eb99f3f85e828d95a29a41b19f..a614ed109d872fee76b1b6cfe47952272b4b3f00 100644 (file)
@@ -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`