diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index be967da2713b3..aee8fb10c2a3a 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -120,7 +120,7 @@ impl Def { Def::TyParam(..) | Def::Struct(..) | Def::Trait(..) | Def::Method(..) | Def::Const(..) | Def::AssociatedConst(..) | Def::PrimTy(..) | Def::Label(..) | Def::SelfTy(..) | Def::Err => { - panic!("attempted .def_id() on invalid {:?}", self) + panic!("attempted .var_id() on invalid {:?}", self) } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6f35d10c99420..e1542688239dd 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 47b91ccb9d6f9..9b6879673238f 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, 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 { + -> Vec> { 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 { + fn resolve_imports_for_module(&mut self, module: Module<'b>) -> Vec> { 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 489bcfbdefdd6..bcd2cd816ed45 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 1d2aecd4e3b7f..1f25bce209314 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 6a203993ccf2d..89f38fa143445 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 }