about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDirk Gadsden <dirk@esherido.com>2016-01-31 19:26:16 -0800
committerDirk Gadsden <dirk@esherido.com>2016-02-02 20:47:34 -0800
commit5ed8e98ea220d797c213a356f354b958f4ccfc49 (patch)
treeae2e8566dfda09d0628a83acc3c91dbfdec455b4
parenta9922419cf84a12b2b9c69f8b261cdd7c287c1a5 (diff)
downloadrust-5ed8e98ea220d797c213a356f354b958f4ccfc49.tar.gz
rust-5ed8e98ea220d797c213a356f354b958f4ccfc49.zip
Add fake import resolutions & targets for names in bad imports
-rw-r--r--src/librustc_resolve/lib.rs5
-rw-r--r--src/librustc_resolve/resolve_imports.rs67
-rw-r--r--src/test/compile-fail/import-from-missing.rs7
-rw-r--r--src/test/compile-fail/import2.rs6
-rw-r--r--src/test/compile-fail/privacy3.rs4
5 files changed, 70 insertions, 19 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 6f35d10c994..e1542688239 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1468,7 +1468,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             match search_module.parent_link {
                 NoParentLink => {
                     // No more parents. This module was unresolved.
-                    debug!("(resolving item in lexical scope) unresolved module");
+                    debug!("(resolving item in lexical scope) unresolved module: no parent module");
                     return Failed(None);
                 }
                 ModuleParentLink(parent_module_node, _) => {
@@ -3109,7 +3109,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
             Indeterminate => None,
             Failed(err) => {
-                debug!("(resolving item path by identifier in lexical scope) failed to resolve {}",
+                debug!("(resolving item path by identifier in lexical scope) failed to \
+                        resolve `{}`",
                        name);
 
                 if let Some((span, msg)) = err {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 47b91ccb9d6..9b687967323 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -11,6 +11,7 @@
 use self::ImportDirectiveSubclass::*;
 
 use DefModifiers;
+use DefOrModule;
 use Module;
 use Namespace::{self, TypeNS, ValueNS};
 use NameBinding;
@@ -50,7 +51,7 @@ pub enum Shadowable {
 }
 
 /// One import directive.
-#[derive(Debug)]
+#[derive(Debug,Clone)]
 pub struct ImportDirective {
     pub module_path: Vec<Name>,
     pub subclass: ImportDirectiveSubclass,
@@ -140,9 +141,11 @@ impl<'a> ImportResolution<'a> {
     }
 }
 
-struct ImportResolvingError {
+struct ImportResolvingError<'a> {
+    /// Module where the error happened
+    source_module: Module<'a>,
+    import_directive: ImportDirective,
     span: Span,
-    path: String,
     help: String,
 }
 
@@ -181,9 +184,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                 // resolving failed
                 if errors.len() > 0 {
                     for e in errors {
-                        resolve_error(self.resolver,
-                                      e.span,
-                                      ResolutionError::UnresolvedImport(Some((&e.path, &e.help))));
+                        self.import_resolving_error(e)
                     }
                 } else {
                     // Report unresolved imports only if no hard error was already reported
@@ -200,11 +201,55 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         }
     }
 
+    /// Resolves an `ImportResolvingError` into the correct enum discriminant
+    /// and passes that on to `resolve_error`.
+    fn import_resolving_error(&self, e: ImportResolvingError) {
+        // If it's a single failed import then create a "fake" import
+        // resolution for it so that later resolve stages won't complain.
+        if let SingleImport(target, _) = e.import_directive.subclass {
+            let mut import_resolutions = e.source_module.import_resolutions.borrow_mut();
+
+            let resolution = import_resolutions.entry((target, ValueNS)).or_insert_with(|| {
+                debug!("(resolving import error) adding import resolution for `{}`",
+                       target);
+
+                ImportResolution::new(e.import_directive.id,
+                                      e.import_directive.is_public)
+            });
+
+            if resolution.target.is_none() {
+                debug!("(resolving import error) adding fake target to import resolution of `{}`",
+                       target);
+
+                let name_binding = NameBinding {
+                    modifiers: DefModifiers::IMPORTABLE,
+                    def_or_module: DefOrModule::Def(Def::Err),
+                    span: None,
+                };
+
+                // Create a fake target pointing to a fake name binding in our
+                // own module
+                let target = Target::new(e.source_module,
+                                         name_binding,
+                                         Shadowable::Always);
+
+                resolution.target = Some(target);
+            }
+        }
+
+        let path = import_path_to_string(&e.import_directive.module_path,
+                                         e.import_directive.subclass);
+
+        resolve_error(self.resolver,
+                      e.span,
+                      ResolutionError::UnresolvedImport(Some((&path, &e.help))));
+    }
+
     /// Attempts to resolve imports for the given module and all of its
     /// submodules.
     fn resolve_imports_for_module_subtree(&mut self,
                                           module_: Module<'b>)
-                                          -> Vec<ImportResolvingError> {
+                                          -> Vec<ImportResolvingError<'b>> {
         let mut errors = Vec::new();
         debug!("(resolving imports for module subtree) resolving {}",
                module_to_string(&*module_));
@@ -232,7 +277,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
     }
 
     /// Attempts to resolve imports for the given module only.
-    fn resolve_imports_for_module(&mut self, module: Module<'b>) -> Vec<ImportResolvingError> {
+    fn resolve_imports_for_module(&mut self, module: Module<'b>) -> Vec<ImportResolvingError<'b>> {
         let mut errors = Vec::new();
 
         if module.all_imports_resolved() {
@@ -254,9 +299,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                         None => (import_directive.span, String::new()),
                     };
                     errors.push(ImportResolvingError {
+                        source_module: module,
+                        import_directive: import_directive.clone(),
                         span: span,
-                        path: import_path_to_string(&import_directive.module_path,
-                                                    import_directive.subclass),
                         help: help,
                     });
                 }
@@ -784,7 +829,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                                  namespace_name,
                                  name);
                 span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg);
-           } else {
+            } else {
                 let target = Target::new(containing_module,
                                          name_binding.clone(),
                                          import_directive.shadowable);
diff --git a/src/test/compile-fail/import-from-missing.rs b/src/test/compile-fail/import-from-missing.rs
index 489bcfbdefd..bcd2cd816ed 100644
--- a/src/test/compile-fail/import-from-missing.rs
+++ b/src/test/compile-fail/import-from-missing.rs
@@ -15,5 +15,8 @@ mod spam {
     pub fn ham() { }
 }
 
-fn main() { ham(); eggs(); }
-//~^ ERROR unresolved name `eggs`
+fn main() {
+    ham();
+    // Expect eggs to pass because the compiler inserts a fake name for it
+    eggs();
+}
diff --git a/src/test/compile-fail/import2.rs b/src/test/compile-fail/import2.rs
index 1d2aecd4e3b..1f25bce2093 100644
--- a/src/test/compile-fail/import2.rs
+++ b/src/test/compile-fail/import2.rs
@@ -11,10 +11,10 @@
 use baz::zed::bar;
 //~^ ERROR unresolved import `baz::zed::bar`. Could not find `zed` in `baz`
 
-
 mod baz {}
 mod zed {
     pub fn bar() { println!("bar3"); }
 }
-fn main() { bar(); }
-//~^ ERROR unresolved name `bar`
+fn main() {
+    bar();
+}
diff --git a/src/test/compile-fail/privacy3.rs b/src/test/compile-fail/privacy3.rs
index 6a203993ccf..89f38fa1434 100644
--- a/src/test/compile-fail/privacy3.rs
+++ b/src/test/compile-fail/privacy3.rs
@@ -27,8 +27,10 @@ pub fn foo() {}
 fn test1() {
     use bar::gpriv;
     //~^ ERROR unresolved import `bar::gpriv`. There is no `gpriv` in `bar`
+
+    // This should pass because the compiler will insert a fake name binding
+    // for `gpriv`
     gpriv();
-    //~^ ERROR unresolved name `gpriv`
 }
 
 #[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }