about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-11-17 07:43:50 -0800
committerGitHub <noreply@github.com>2016-11-17 07:43:50 -0800
commitc57b8261496d548e0a3cd8468061ddc5a4dcafe2 (patch)
treeaa6b693f0cda3854318d75b7708f593f52b4f645 /src
parent5bd1e7f59ffe6126db57ea94b90690d1ac39b932 (diff)
parent6cb33a089fc4727bc070899f57aab3be1b215785 (diff)
downloadrust-c57b8261496d548e0a3cd8468061ddc5a4dcafe2.tar.gz
rust-c57b8261496d548e0a3cd8468061ddc5a4dcafe2.zip
Auto merge of #37732 - jseyfried:use_extern_macros, r=nrc
Support `use`ing externally defined macros behind `#![feature(use_extern_macros)]`

With `#![feature(use_extern_macros)]`,
 - A name collision between macros from different upstream crates is much less of an issue since we can `use` the macros in different submodules or rename with `as`.
 - We can reexport macros with `pub use`, so `#![feature(macro_reexport)]` is no longer needed.
 - These reexports are allowed in any module, so crates can expose a macro-modular interface.

If a macro invocation can resolve to both a `use` import and a `macro_rules!` or `#[macro_use]`, it is an ambiguity error.

r? @nrc
Diffstat (limited to 'src')
-rw-r--r--src/librustc_driver/driver.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs152
-rw-r--r--src/librustc_resolve/check_unused.rs6
-rw-r--r--src/librustc_resolve/lib.rs231
-rw-r--r--src/librustc_resolve/macros.rs173
-rw-r--r--src/librustc_resolve/resolve_imports.rs345
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/ext/expand.rs13
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/test/compile-fail/blind-item-block-item-shadow.rs2
-rw-r--r--src/test/compile-fail/double-type-import.rs2
-rw-r--r--src/test/compile-fail/imports/auxiliary/two_macros.rs15
-rw-r--r--src/test/compile-fail/imports/duplicate.rs4
-rw-r--r--src/test/compile-fail/imports/macros.rs55
14 files changed, 618 insertions, 386 deletions
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 2dd83f70823..5466c8871d4 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -755,8 +755,6 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
          || ast_validation::check_crate(sess, &krate));
 
     time(sess.time_passes(), "name resolution", || -> CompileResult {
-        resolver.resolve_imports();
-
         // Since import resolution will eventually happen in expansion,
         // don't perform `after_expand` until after import resolution.
         after_expand(&krate)?;
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 99e7a9042c0..627c72ff8c9 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -15,7 +15,7 @@
 
 use macros::{InvocationData, LegacyScope};
 use resolve_imports::ImportDirective;
-use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
+use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
 use {Resolver, Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
 use Namespace::{self, TypeNS, ValueNS, MacroNS};
 use ResolveResult::Success;
@@ -37,6 +37,7 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind};
 use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind};
 use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::ext::base::SyntaxExtension;
+use syntax::ext::base::Determinacy::Undetermined;
 use syntax::ext::expand::mark_tts;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
@@ -45,15 +46,25 @@ use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
 
-impl<'a> ToNameBinding<'a> for (Module<'a>, Span, ty::Visibility) {
+impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) {
     fn to_name_binding(self) -> NameBinding<'a> {
-        NameBinding { kind: NameBindingKind::Module(self.0), span: self.1, vis: self.2 }
+        NameBinding {
+            kind: NameBindingKind::Module(self.0),
+            vis: self.1,
+            span: self.2,
+            expansion: self.3,
+        }
     }
 }
 
-impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
+impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) {
     fn to_name_binding(self) -> NameBinding<'a> {
-        NameBinding { kind: NameBindingKind::Def(self.0), span: self.1, vis: self.2 }
+        NameBinding {
+            kind: NameBindingKind::Def(self.0),
+            vis: self.1,
+            span: self.2,
+            expansion: self.3,
+        }
     }
 }
 
@@ -147,9 +158,14 @@ impl<'b> Resolver<'b> {
                                 .emit();
                         }
 
-                        let subclass = ImportDirectiveSubclass::single(binding.name, source.name);
-                        let span = view_path.span;
-                        self.add_import_directive(module_path, subclass, span, item.id, vis);
+                        let subclass = SingleImport {
+                            target: binding.name,
+                            source: source.name,
+                            result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
+                        };
+                        self.add_import_directive(
+                            module_path, subclass, view_path.span, item.id, vis, expansion,
+                        );
                     }
                     ViewPathList(_, ref source_items) => {
                         // Make sure there's at most one `mod` import in the list.
@@ -195,9 +211,15 @@ impl<'b> Resolver<'b> {
                                     (module_path.to_vec(), name, rename)
                                 }
                             };
-                            let subclass = ImportDirectiveSubclass::single(rename, name);
-                            let (span, id) = (source_item.span, source_item.node.id);
-                            self.add_import_directive(module_path, subclass, span, id, vis);
+                            let subclass = SingleImport {
+                                target: rename,
+                                source: name,
+                                result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
+                            };
+                            let id = source_item.node.id;
+                            self.add_import_directive(
+                                module_path, subclass, source_item.span, id, vis, expansion,
+                            );
                         }
                     }
                     ViewPathGlob(_) => {
@@ -205,8 +227,9 @@ impl<'b> Resolver<'b> {
                             is_prelude: is_prelude,
                             max_vis: Cell::new(ty::Visibility::PrivateExternal),
                         };
-                        let span = view_path.span;
-                        self.add_import_directive(module_path, subclass, span, item.id, vis);
+                        self.add_import_directive(
+                            module_path, subclass, view_path.span, item.id, vis, expansion,
+                        );
                     }
                 }
             }
@@ -217,7 +240,7 @@ impl<'b> Resolver<'b> {
                 // n.b. we don't need to look at the path option here, because cstore already did
                 let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
                 let module = self.get_extern_crate_root(crate_id);
-                let binding = (module, sp, ty::Visibility::Public).to_name_binding();
+                let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding();
                 let binding = self.arenas.alloc_name_binding(binding);
                 let directive = self.arenas.alloc_import_directive(ImportDirective {
                     id: item.id,
@@ -227,6 +250,7 @@ impl<'b> Resolver<'b> {
                     span: item.span,
                     module_path: Vec::new(),
                     vis: Cell::new(vis),
+                    expansion: expansion,
                 });
                 let imported_binding = self.import(binding, directive);
                 self.define(parent, name, TypeNS, imported_binding);
@@ -245,7 +269,7 @@ impl<'b> Resolver<'b> {
                     normal_ancestor_id: Some(item.id),
                     ..ModuleS::new(Some(parent), ModuleKind::Def(def, name))
                 });
-                self.define(parent, name, TypeNS, (module, sp, vis));
+                self.define(parent, name, TypeNS, (module, vis, sp, expansion));
                 self.module_map.insert(item.id, module);
 
                 // Descend into the module.
@@ -258,30 +282,30 @@ impl<'b> Resolver<'b> {
             ItemKind::Static(_, m, _) => {
                 let mutbl = m == Mutability::Mutable;
                 let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
-                self.define(parent, name, ValueNS, (def, sp, vis));
+                self.define(parent, name, ValueNS, (def, vis, sp, expansion));
             }
             ItemKind::Const(..) => {
                 let def = Def::Const(self.definitions.local_def_id(item.id));
-                self.define(parent, name, ValueNS, (def, sp, vis));
+                self.define(parent, name, ValueNS, (def, vis, sp, expansion));
             }
             ItemKind::Fn(..) => {
                 let def = Def::Fn(self.definitions.local_def_id(item.id));
-                self.define(parent, name, ValueNS, (def, sp, vis));
+                self.define(parent, name, ValueNS, (def, vis, sp, expansion));
             }
 
             // These items live in the type namespace.
             ItemKind::Ty(..) => {
                 let def = Def::TyAlias(self.definitions.local_def_id(item.id));
-                self.define(parent, name, TypeNS, (def, sp, vis));
+                self.define(parent, name, TypeNS, (def, vis, sp, expansion));
             }
 
             ItemKind::Enum(ref enum_definition, _) => {
                 let def = Def::Enum(self.definitions.local_def_id(item.id));
                 let module = self.new_module(parent, ModuleKind::Def(def, name), true);
-                self.define(parent, name, TypeNS, (module, sp, vis));
+                self.define(parent, name, TypeNS, (module, vis, sp, expansion));
 
                 for variant in &(*enum_definition).variants {
-                    self.build_reduced_graph_for_variant(variant, module, vis);
+                    self.build_reduced_graph_for_variant(variant, module, vis, expansion);
                 }
             }
 
@@ -289,14 +313,14 @@ impl<'b> Resolver<'b> {
             ItemKind::Struct(ref struct_def, _) => {
                 // Define a name in the type namespace.
                 let def = Def::Struct(self.definitions.local_def_id(item.id));
-                self.define(parent, name, TypeNS, (def, sp, vis));
+                self.define(parent, name, TypeNS, (def, vis, sp, expansion));
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
                 if !struct_def.is_struct() {
                     let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
                                                    CtorKind::from_ast(struct_def));
-                    self.define(parent, name, ValueNS, (ctor_def, sp, vis));
+                    self.define(parent, name, ValueNS, (ctor_def, vis, sp, expansion));
                 }
 
                 // Record field names for error reporting.
@@ -310,7 +334,7 @@ impl<'b> Resolver<'b> {
 
             ItemKind::Union(ref vdata, _) => {
                 let def = Def::Union(self.definitions.local_def_id(item.id));
-                self.define(parent, name, TypeNS, (def, sp, vis));
+                self.define(parent, name, TypeNS, (def, vis, sp, expansion));
 
                 // Record field names for error reporting.
                 let field_names = vdata.fields().iter().filter_map(|field| {
@@ -329,7 +353,7 @@ impl<'b> Resolver<'b> {
                 // Add all the items within to a new module.
                 let module =
                     self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), name), true);
-                self.define(parent, name, TypeNS, (module, sp, vis));
+                self.define(parent, name, TypeNS, (module, vis, sp, expansion));
                 self.current_module = module;
             }
             ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
@@ -341,37 +365,38 @@ impl<'b> Resolver<'b> {
     fn build_reduced_graph_for_variant(&mut self,
                                        variant: &Variant,
                                        parent: Module<'b>,
-                                       vis: ty::Visibility) {
+                                       vis: ty::Visibility,
+                                       expansion: Mark) {
         let name = variant.node.name.name;
         let def_id = self.definitions.local_def_id(variant.node.data.id());
 
         // Define a name in the type namespace.
         let def = Def::Variant(def_id);
-        self.define(parent, name, TypeNS, (def, variant.span, vis));
+        self.define(parent, name, TypeNS, (def, vis, variant.span, expansion));
 
         // Define a constructor name in the value namespace.
         // Braced variants, unlike structs, generate unusable names in
         // value namespace, they are reserved for possible future use.
         let ctor_kind = CtorKind::from_ast(&variant.node.data);
         let ctor_def = Def::VariantCtor(def_id, ctor_kind);
-        self.define(parent, name, ValueNS, (ctor_def, variant.span, vis));
+        self.define(parent, name, ValueNS, (ctor_def, vis, variant.span, expansion));
     }
 
     /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item(&mut self, foreign_item: &ForeignItem) {
+    fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) {
         let parent = self.current_module;
-        let name = foreign_item.ident.name;
+        let name = item.ident.name;
 
-        let def = match foreign_item.node {
+        let def = match item.node {
             ForeignItemKind::Fn(..) => {
-                Def::Fn(self.definitions.local_def_id(foreign_item.id))
+                Def::Fn(self.definitions.local_def_id(item.id))
             }
             ForeignItemKind::Static(_, m) => {
-                Def::Static(self.definitions.local_def_id(foreign_item.id), m)
+                Def::Static(self.definitions.local_def_id(item.id), m)
             }
         };
-        let vis = self.resolve_visibility(&foreign_item.vis);
-        self.define(parent, name, ValueNS, (def, foreign_item.span, vis));
+        let vis = self.resolve_visibility(&item.vis);
+        self.define(parent, name, ValueNS, (def, vis, item.span, expansion));
     }
 
     fn build_reduced_graph_for_block(&mut self, block: &Block) {
@@ -390,8 +415,7 @@ impl<'b> Resolver<'b> {
     }
 
     /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>,
-                                                  child: Export) {
+    fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: Export) {
         let name = child.name;
         let def = child.def;
         let def_id = def.def_id();
@@ -404,24 +428,24 @@ impl<'b> Resolver<'b> {
         match def {
             Def::Mod(..) | Def::Enum(..) => {
                 let module = self.new_module(parent, ModuleKind::Def(def, name), false);
-                self.define(parent, name, TypeNS, (module, DUMMY_SP, vis));
+                self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
             }
             Def::Variant(..) => {
-                self.define(parent, name, TypeNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
             }
             Def::VariantCtor(..) => {
-                self.define(parent, name, ValueNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
             }
             Def::Fn(..) |
             Def::Static(..) |
             Def::Const(..) |
             Def::AssociatedConst(..) |
             Def::Method(..) => {
-                self.define(parent, name, ValueNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
             }
             Def::Trait(..) => {
                 let module = self.new_module(parent, ModuleKind::Def(def, name), false);
-                self.define(parent, name, TypeNS, (module, DUMMY_SP, vis));
+                self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
 
                 // If this is a trait, add all the trait item names to the trait info.
                 let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id);
@@ -433,27 +457,27 @@ impl<'b> Resolver<'b> {
                 }
             }
             Def::TyAlias(..) | Def::AssociatedTy(..) => {
-                self.define(parent, name, TypeNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
             }
             Def::Struct(..) => {
-                self.define(parent, name, TypeNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
 
                 // Record field names for error reporting.
                 let field_names = self.session.cstore.struct_field_names(def_id);
                 self.insert_field_names(def_id, field_names);
             }
             Def::StructCtor(..) => {
-                self.define(parent, name, ValueNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
             }
             Def::Union(..) => {
-                self.define(parent, name, TypeNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
 
                 // Record field names for error reporting.
                 let field_names = self.session.cstore.struct_field_names(def_id);
                 self.insert_field_names(def_id, field_names);
             }
             Def::Macro(..) => {
-                self.define(parent, name, MacroNS, (def, DUMMY_SP, vis));
+                self.define(parent, name, MacroNS, (def, vis, DUMMY_SP, Mark::root()));
             }
             Def::Local(..) |
             Def::PrimTy(..) |
@@ -479,9 +503,11 @@ impl<'b> Resolver<'b> {
         })
     }
 
-    pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> {
-        let def_id = match def {
-            Def::Macro(def_id) => def_id,
+    pub fn get_macro(&mut self, binding: &'b NameBinding<'b>) -> Rc<SyntaxExtension> {
+        let def_id = match binding.kind {
+            NameBindingKind::Def(Def::Macro(def_id)) => def_id,
+            NameBindingKind::Import { binding, .. } => return self.get_macro(binding),
+            NameBindingKind::Ambiguity { b1, .. } => return self.get_macro(b1),
             _ => panic!("Expected Def::Macro(..)"),
         };
         if let Some(ext) = self.macro_map.get(&def_id) {
@@ -518,10 +544,14 @@ impl<'b> Resolver<'b> {
         module.populated.set(true)
     }
 
-    fn legacy_import_macro(&mut self, name: Name, def: Def, span: Span, allow_shadowing: bool) {
-        self.used_crates.insert(def.def_id().krate);
+    fn legacy_import_macro(&mut self,
+                           name: Name,
+                           binding: &'b NameBinding<'b>,
+                           span: Span,
+                           allow_shadowing: bool) {
+        self.used_crates.insert(binding.def().def_id().krate);
         self.macro_names.insert(name);
-        if self.builtin_macros.insert(name, def.def_id()).is_some() && !allow_shadowing {
+        if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
             let msg = format!("`{}` is already in scope", name);
             let note =
                 "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
@@ -548,13 +578,13 @@ impl<'b> Resolver<'b> {
 
         if let Some(span) = legacy_imports.import_all {
             module.for_each_child(|name, ns, binding| if ns == MacroNS {
-                self.legacy_import_macro(name, binding.def(), span, allow_shadowing);
+                self.legacy_import_macro(name, binding, span, allow_shadowing);
             });
         } else {
             for (name, span) in legacy_imports.imports {
-                let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
+                let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None);
                 if let Success(binding) = result {
-                    self.legacy_import_macro(name, binding.def(), span, allow_shadowing);
+                    self.legacy_import_macro(name, binding, span, allow_shadowing);
                 } else {
                     span_err!(self.session, span, E0469, "imported macro not found");
                 }
@@ -562,7 +592,7 @@ impl<'b> Resolver<'b> {
         }
         for (name, span) in legacy_imports.reexports {
             self.used_crates.insert(module.def_id().unwrap().krate);
-            let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
+            let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None);
             if let Success(binding) = result {
                 self.macro_exports.push(Export { name: name, def: binding.def() });
             } else {
@@ -638,7 +668,9 @@ pub struct BuildReducedGraphVisitor<'a, 'b: 'a> {
 
 impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
-        let invocation = self.resolver.invocations[&Mark::from_placeholder_id(id)];
+        let mark = Mark::from_placeholder_id(id);
+        self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
+        let invocation = self.resolver.invocations[&mark];
         invocation.module.set(self.resolver.current_module);
         invocation.legacy_scope.set(self.legacy_scope);
         invocation
@@ -691,7 +723,7 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        self.resolver.build_reduced_graph_for_foreign_item(foreign_item);
+        self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion);
         visit::walk_foreign_item(self, foreign_item);
     }
 
@@ -728,7 +760,7 @@ impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
         self.resolver.trait_item_map.insert((item.ident.name, def_id), is_static_method);
 
         let vis = ty::Visibility::Public;
-        self.resolver.define(parent, item.ident.name, ns, (def, item.span, vis));
+        self.resolver.define(parent, item.ident.name, ns, (def, vis, item.span, self.expansion));
 
         self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor
         visit::walk_trait_item(self, item);
diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs
index 36e05a43341..492c5e695bb 100644
--- a/src/librustc_resolve/check_unused.rs
+++ b/src/librustc_resolve/check_unused.rs
@@ -22,7 +22,6 @@
 use std::ops::{Deref, DerefMut};
 
 use Resolver;
-use Namespace::{TypeNS, ValueNS};
 
 use rustc::lint;
 use rustc::util::nodemap::NodeMap;
@@ -56,8 +55,9 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
     // We have information about whether `use` (import) directives are actually
     // used now. If an import is not used at all, we signal a lint error.
     fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) {
-        if !self.used_imports.contains(&(id, TypeNS)) &&
-           !self.used_imports.contains(&(id, ValueNS)) {
+        let mut used = false;
+        self.per_ns(|this, ns| used |= this.used_imports.contains(&(id, ns)));
+        if !used {
             if self.maybe_unused_trait_imports.contains(&id) {
                 // Check later.
                 return;
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 73b7b185b24..a3a60e4f6d7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -76,7 +76,7 @@ use std::fmt;
 use std::mem::replace;
 use std::rc::Rc;
 
-use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution};
+use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
 use macros::{InvocationData, LegacyBinding, LegacyScope};
 
 // NB: This module needs to be declared first so diagnostics are
@@ -536,6 +536,34 @@ pub enum Namespace {
     MacroNS,
 }
 
+#[derive(Clone, Default, Debug)]
+pub struct PerNS<T> {
+    value_ns: T,
+    type_ns: T,
+    macro_ns: Option<T>,
+}
+
+impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
+    type Output = T;
+    fn index(&self, ns: Namespace) -> &T {
+        match ns {
+            ValueNS => &self.value_ns,
+            TypeNS => &self.type_ns,
+            MacroNS => self.macro_ns.as_ref().unwrap(),
+        }
+    }
+}
+
+impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
+    fn index_mut(&mut self, ns: Namespace) -> &mut T {
+        match ns {
+            ValueNS => &mut self.value_ns,
+            TypeNS => &mut self.type_ns,
+            MacroNS => self.macro_ns.as_mut().unwrap(),
+        }
+    }
+}
+
 impl<'a> Visitor for Resolver<'a> {
     fn visit_item(&mut self, item: &Item) {
         self.resolve_item(item);
@@ -612,7 +640,7 @@ impl<'a> Visitor for Resolver<'a> {
         };
 
         // Create a value rib for the function.
-        self.value_ribs.push(Rib::new(rib_kind));
+        self.ribs[ValueNS].push(Rib::new(rib_kind));
 
         // Create a label rib for the function.
         self.label_ribs.push(Rib::new(rib_kind));
@@ -642,13 +670,13 @@ impl<'a> Visitor for Resolver<'a> {
         debug!("(resolving function) leaving function");
 
         self.label_ribs.pop();
-        self.value_ribs.pop();
+        self.ribs[ValueNS].pop();
     }
 }
 
 pub type ErrorMessage = Option<(Span, String)>;
 
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub enum ResolveResult<T> {
     Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message.
     Indeterminate, // Couldn't determine due to unresolved globs.
@@ -656,14 +684,6 @@ pub enum ResolveResult<T> {
 }
 
 impl<T> ResolveResult<T> {
-    fn and_then<U, F: FnOnce(T) -> ResolveResult<U>>(self, f: F) -> ResolveResult<U> {
-        match self {
-            Failed(msg) => Failed(msg),
-            Indeterminate => Indeterminate,
-            Success(t) => f(t),
-        }
-    }
-
     fn success(self) -> Option<T> {
         match self {
             Success(t) => Some(t),
@@ -798,6 +818,10 @@ pub struct ModuleS<'a> {
     normal_ancestor_id: Option<NodeId>,
 
     resolutions: RefCell<FxHashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
+    legacy_macro_resolutions: RefCell<Vec<(Mark, Name, Span)>>,
+
+    // Macro invocations that can expand into items in this module.
+    unresolved_invocations: RefCell<FxHashSet<Mark>>,
 
     no_implicit_prelude: bool,
 
@@ -822,6 +846,8 @@ impl<'a> ModuleS<'a> {
             kind: kind,
             normal_ancestor_id: None,
             resolutions: RefCell::new(FxHashMap()),
+            legacy_macro_resolutions: RefCell::new(Vec::new()),
+            unresolved_invocations: RefCell::new(FxHashSet()),
             no_implicit_prelude: false,
             glob_importers: RefCell::new(Vec::new()),
             globs: RefCell::new((Vec::new())),
@@ -877,6 +903,7 @@ impl<'a> fmt::Debug for ModuleS<'a> {
 #[derive(Clone, Debug)]
 pub struct NameBinding<'a> {
     kind: NameBindingKind<'a>,
+    expansion: Mark,
     span: Span,
     vis: ty::Visibility,
 }
@@ -911,6 +938,7 @@ struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
 struct AmbiguityError<'a> {
     span: Span,
     name: Name,
+    lexical: bool,
     b1: &'a NameBinding<'a>,
     b2: &'a NameBinding<'a>,
 }
@@ -969,7 +997,7 @@ impl<'a> NameBinding<'a> {
     fn is_glob_import(&self) -> bool {
         match self.kind {
             NameBindingKind::Import { directive, .. } => directive.is_glob(),
-            NameBindingKind::Ambiguity { .. } => true,
+            NameBindingKind::Ambiguity { b1, .. } => b1.is_glob_import(),
             _ => false,
         }
     }
@@ -1044,12 +1072,9 @@ pub struct Resolver<'a> {
     // The module that represents the current item scope.
     current_module: Module<'a>,
 
-    // The current set of local scopes, for values.
+    // The current set of local scopes for types and values.
     // FIXME #4948: Reuse ribs to avoid allocation.
-    value_ribs: Vec<Rib<'a>>,
-
-    // The current set of local scopes, for types.
-    type_ribs: Vec<Rib<'a>>,
+    ribs: PerNS<Vec<Rib<'a>>>,
 
     // The current set of local scopes, for labels.
     label_ribs: Vec<Rib<'a>>,
@@ -1107,11 +1132,12 @@ pub struct Resolver<'a> {
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
     new_import_semantics: bool, // true if `#![feature(item_like_imports)]`
+    use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
 
     pub exported_macros: Vec<ast::MacroDef>,
     crate_loader: &'a mut CrateLoader,
     macro_names: FxHashSet<Name>,
-    builtin_macros: FxHashMap<Name, DefId>,
+    builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
     lexical_macro_resolutions: Vec<(Name, LegacyScope<'a>)>,
     macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
     macro_exports: Vec<Export>,
@@ -1268,8 +1294,11 @@ impl<'a> Resolver<'a> {
             indeterminate_imports: Vec::new(),
 
             current_module: graph_root,
-            value_ribs: vec![Rib::new(ModuleRibKind(graph_root))],
-            type_ribs: vec![Rib::new(ModuleRibKind(graph_root))],
+            ribs: PerNS {
+                value_ns: vec![Rib::new(ModuleRibKind(graph_root))],
+                type_ns: vec![Rib::new(ModuleRibKind(graph_root))],
+                macro_ns: None,
+            },
             label_ribs: Vec::new(),
 
             current_trait_ref: None,
@@ -1300,10 +1329,12 @@ impl<'a> Resolver<'a> {
             arenas: arenas,
             dummy_binding: arenas.alloc_name_binding(NameBinding {
                 kind: NameBindingKind::Def(Def::Err),
+                expansion: Mark::root(),
                 span: DUMMY_SP,
                 vis: ty::Visibility::Public,
             }),
             new_import_semantics: session.features.borrow().item_like_imports,
+            use_extern_macros: session.features.borrow().use_extern_macros,
 
             exported_macros: Vec::new(),
             crate_loader: crate_loader,
@@ -1329,8 +1360,20 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    fn per_ns<T, F: FnMut(&mut Self, Namespace) -> T>(&mut self, mut f: F) -> PerNS<T> {
+        PerNS {
+            type_ns: f(self, TypeNS),
+            value_ns: f(self, ValueNS),
+            macro_ns: match self.use_extern_macros {
+                true => Some(f(self, MacroNS)),
+                false => None,
+            },
+        }
+    }
+
     /// Entry point to crate resolution.
     pub fn resolve_crate(&mut self, krate: &Crate) {
+        ImportResolver { resolver: self }.finalize_imports();
         self.current_module = self.graph_root;
         visit::walk_crate(self, krate);
 
@@ -1347,14 +1390,6 @@ impl<'a> Resolver<'a> {
         })
     }
 
-    fn get_ribs<'b>(&'b mut self, ns: Namespace) -> &'b mut Vec<Rib<'a>> {
-        match ns {
-            ValueNS => &mut self.value_ribs,
-            TypeNS => &mut self.type_ribs,
-            MacroNS => panic!("The macro namespace has no ribs"),
-        }
-    }
-
     fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
                   -> bool /* true if an error was reported */ {
         // track extern crates for unused_extern_crate lint
@@ -1371,8 +1406,9 @@ impl<'a> Resolver<'a> {
             }
             NameBindingKind::Import { .. } => false,
             NameBindingKind::Ambiguity { b1, b2 } => {
-                let ambiguity_error = AmbiguityError { span: span, name: name, b1: b1, b2: b2 };
-                self.ambiguity_errors.push(ambiguity_error);
+                self.ambiguity_errors.push(AmbiguityError {
+                    span: span, name: name, lexical: false, b1: b1, b2: b2,
+                });
                 true
             }
             _ => false
@@ -1406,7 +1442,7 @@ impl<'a> Resolver<'a> {
                                      -> ResolveResult<Module<'a>> {
         fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>)
                                        -> Option<Module<'a>> {
-            match this.resolve_name_in_module(module, needle, TypeNS, false, None) {
+            match this.resolve_name_in_module(module, needle, TypeNS, false, false, None) {
                 Success(binding) if binding.is_extern_crate() => Some(module),
                 _ => if let (&ModuleKind::Def(..), Some(parent)) = (&module.kind, module.parent) {
                     search_parent_externals(this, needle, parent)
@@ -1424,7 +1460,7 @@ impl<'a> Resolver<'a> {
         // modules as we go.
         while index < module_path_len {
             let name = module_path[index].name;
-            match self.resolve_name_in_module(search_module, name, TypeNS, false, span) {
+            match self.resolve_name_in_module(search_module, name, TypeNS, false, false, span) {
                 Failed(_) => {
                     let segment_name = name.as_str();
                     let module_name = module_to_string(search_module);
@@ -1570,8 +1606,8 @@ impl<'a> Resolver<'a> {
         }
 
         // Walk backwards up the ribs in scope.
-        for i in (0 .. self.get_ribs(ns).len()).rev() {
-            if let Some(def) = self.get_ribs(ns)[i].bindings.get(&ident).cloned() {
+        for i in (0 .. self.ribs[ns].len()).rev() {
+            if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::LocalDef(LocalDef {
                     ribs: Some((ns, i)),
@@ -1579,9 +1615,9 @@ impl<'a> Resolver<'a> {
                 }));
             }
 
-            if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind {
+            if let ModuleRibKind(module) = self.ribs[ns][i].kind {
                 let name = ident.name;
-                let item = self.resolve_name_in_module(module, name, ns, true, record_used);
+                let item = self.resolve_name_in_module(module, name, ns, true, false, record_used);
                 if let Success(binding) = item {
                     // The ident resolves to an item.
                     return Some(LexicalScopeBinding::Item(binding));
@@ -1590,14 +1626,14 @@ impl<'a> Resolver<'a> {
                 if let ModuleKind::Block(..) = module.kind { // We can see through blocks
                 } else if !module.no_implicit_prelude {
                     return self.prelude.and_then(|prelude| {
-                        self.resolve_name_in_module(prelude, name, ns, false, None).success()
+                        self.resolve_name_in_module(prelude, name, ns, false, false, None).success()
                     }).map(LexicalScopeBinding::Item)
                 } else {
                     return None;
                 }
             }
 
-            if let MacroDefinition(mac) = self.get_ribs(ns)[i].kind {
+            if let MacroDefinition(mac) = self.ribs[ns][i].kind {
                 // If an invocation of this macro created `ident`, give up on `ident`
                 // and switch to `ident`'s source from the macro definition.
                 let (source_ctxt, source_macro) = ident.ctxt.source();
@@ -1682,14 +1718,15 @@ impl<'a> Resolver<'a> {
         if let Some(module) = module {
             // Move down in the graph.
             let orig_module = replace(&mut self.current_module, module);
-            self.value_ribs.push(Rib::new(ModuleRibKind(module)));
-            self.type_ribs.push(Rib::new(ModuleRibKind(module)));
+            self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
+            self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
 
+            self.finalize_current_module_macro_resolutions();
             f(self);
 
             self.current_module = orig_module;
-            self.value_ribs.pop();
-            self.type_ribs.pop();
+            self.ribs[ValueNS].pop();
+            self.ribs[TypeNS].pop();
         } else {
             f(self);
         }
@@ -1864,7 +1901,7 @@ impl<'a> Resolver<'a> {
                     function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def);
                     self.record_def(type_parameter.id, PathResolution::new(def));
                 }
-                self.type_ribs.push(function_type_rib);
+                self.ribs[TypeNS].push(function_type_rib);
             }
 
             NoTypeParameters => {
@@ -1875,7 +1912,7 @@ impl<'a> Resolver<'a> {
         f(self);
 
         if let HasTypeParameters(..) = type_parameters {
-            self.type_ribs.pop();
+            self.ribs[TypeNS].pop();
         }
     }
 
@@ -1890,11 +1927,11 @@ impl<'a> Resolver<'a> {
     fn with_constant_rib<F>(&mut self, f: F)
         where F: FnOnce(&mut Resolver)
     {
-        self.value_ribs.push(Rib::new(ConstantItemRibKind));
-        self.type_ribs.push(Rib::new(ConstantItemRibKind));
+        self.ribs[ValueNS].push(Rib::new(ConstantItemRibKind));
+        self.ribs[TypeNS].push(Rib::new(ConstantItemRibKind));
         f(self);
-        self.type_ribs.pop();
-        self.value_ribs.pop();
+        self.ribs[TypeNS].pop();
+        self.ribs[ValueNS].pop();
     }
 
     fn resolve_trait_reference(&mut self,
@@ -2004,9 +2041,9 @@ impl<'a> Resolver<'a> {
 
         // plain insert (no renaming, types are not currently hygienic....)
         self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def);
-        self.type_ribs.push(self_type_rib);
+        self.ribs[TypeNS].push(self_type_rib);
         f(self);
-        self.type_ribs.pop();
+        self.ribs[TypeNS].pop();
     }
 
     fn resolve_implementation(&mut self,
@@ -2160,7 +2197,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_arm(&mut self, arm: &Arm) {
-        self.value_ribs.push(Rib::new(NormalRibKind));
+        self.ribs[ValueNS].push(Rib::new(NormalRibKind));
 
         let mut bindings_list = FxHashMap();
         for pattern in &arm.pats {
@@ -2174,7 +2211,7 @@ impl<'a> Resolver<'a> {
         walk_list!(self, visit_expr, &arm.guard);
         self.visit_expr(&arm.body);
 
-        self.value_ribs.pop();
+        self.ribs[ValueNS].pop();
     }
 
     fn resolve_block(&mut self, block: &Block) {
@@ -2186,11 +2223,12 @@ impl<'a> Resolver<'a> {
         let mut num_macro_definition_ribs = 0;
         if let Some(anonymous_module) = anonymous_module {
             debug!("(resolving block) found anonymous module, moving down");
-            self.value_ribs.push(Rib::new(ModuleRibKind(anonymous_module)));
-            self.type_ribs.push(Rib::new(ModuleRibKind(anonymous_module)));
+            self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module)));
+            self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module)));
             self.current_module = anonymous_module;
+            self.finalize_current_module_macro_resolutions();
         } else {
-            self.value_ribs.push(Rib::new(NormalRibKind));
+            self.ribs[ValueNS].push(Rib::new(NormalRibKind));
         }
 
         // Descend into the block.
@@ -2198,7 +2236,7 @@ impl<'a> Resolver<'a> {
             if let Some(marks) = self.macros_at_scope.remove(&stmt.id) {
                 num_macro_definition_ribs += marks.len() as u32;
                 for mark in marks {
-                    self.value_ribs.push(Rib::new(MacroDefinition(mark)));
+                    self.ribs[ValueNS].push(Rib::new(MacroDefinition(mark)));
                     self.label_ribs.push(Rib::new(MacroDefinition(mark)));
                 }
             }
@@ -2209,12 +2247,12 @@ impl<'a> Resolver<'a> {
         // Move back up.
         self.current_module = orig_module;
         for _ in 0 .. num_macro_definition_ribs {
-            self.value_ribs.pop();
+            self.ribs[ValueNS].pop();
             self.label_ribs.pop();
         }
-        self.value_ribs.pop();
+        self.ribs[ValueNS].pop();
         if let Some(_) = anonymous_module {
-            self.type_ribs.pop();
+            self.ribs[TypeNS].pop();
         }
         debug!("(resolving block) leaving block");
     }
@@ -2333,7 +2371,7 @@ impl<'a> Resolver<'a> {
             Some(..) if pat_src == PatternSource::Match => {
                 // `Variant1(a) | Variant2(a)`, ok
                 // Reuse definition from the first `a`.
-                def = self.value_ribs.last_mut().unwrap().bindings[&ident.node];
+                def = self.ribs[ValueNS].last_mut().unwrap().bindings[&ident.node];
             }
             Some(..) => {
                 span_bug!(ident.span, "two bindings with the same name from \
@@ -2343,7 +2381,7 @@ impl<'a> Resolver<'a> {
                 // A completely fresh binding, add to the lists if it's valid.
                 if ident.node.name != keywords::Invalid.name() {
                     bindings.insert(ident.node, outer_pat_id);
-                    self.value_ribs.last_mut().unwrap().bindings.insert(ident.node, def);
+                    self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident.node, def);
                 }
             }
         }
@@ -2627,9 +2665,8 @@ impl<'a> Resolver<'a> {
     // Resolve a local definition, potentially adjusting for closures.
     fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
         let ribs = match local_def.ribs {
-            Some((TypeNS, i)) => &self.type_ribs[i + 1..],
-            Some((ValueNS, i)) => &self.value_ribs[i + 1..],
-            _ => &[] as &[_],
+            Some((ns, i)) => &self.ribs[ns][i + 1..],
+            None => &[] as &[_],
         };
         let mut def = local_def.def;
         match def {
@@ -2723,8 +2760,7 @@ impl<'a> Resolver<'a> {
         let module_path =
             segments.split_last().unwrap().1.iter().map(|ps| ps.identifier).collect::<Vec<_>>();
 
-        let containing_module;
-        match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) {
+        let module = match self.resolve_module_path(&module_path, UseLexicalScope, Some(span)) {
             Failed(err) => {
                 if let Some((span, msg)) = err {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@@ -2732,14 +2768,11 @@ impl<'a> Resolver<'a> {
                 return Err(true);
             }
             Indeterminate => return Err(false),
-            Success(resulting_module) => {
-                containing_module = resulting_module;
-            }
-        }
+            Success(module) => module,
+        };
 
         let name = segments.last().unwrap().identifier.name;
-        let result =
-            self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
+        let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span));
         result.success().ok_or(false)
     }
 
@@ -2751,10 +2784,9 @@ impl<'a> Resolver<'a> {
         where T: Named,
     {
         let module_path = segments.split_last().unwrap().1.iter().map(T::ident).collect::<Vec<_>>();
-        let root_module = self.graph_root;
+        let root = self.graph_root;
 
-        let containing_module;
-        match self.resolve_module_path_from_root(root_module, &module_path, 0, Some(span)) {
+        let module = match self.resolve_module_path_from_root(root, &module_path, 0, Some(span)) {
             Failed(err) => {
                 if let Some((span, msg)) = err {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@@ -2764,14 +2796,11 @@ impl<'a> Resolver<'a> {
 
             Indeterminate => return Err(false),
 
-            Success(resulting_module) => {
-                containing_module = resulting_module;
-            }
-        }
+            Success(module) => module,
+        };
 
         let name = segments.last().unwrap().ident().name;
-        let result =
-            self.resolve_name_in_module(containing_module, name, namespace, false, Some(span));
+        let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span));
         result.success().ok_or(false)
     }
 
@@ -2791,8 +2820,8 @@ impl<'a> Resolver<'a> {
         where F: FnOnce(&mut Resolver<'a>) -> T,
     {
         self.with_empty_ribs(|this| {
-            this.value_ribs.push(Rib::new(ModuleRibKind(module)));
-            this.type_ribs.push(Rib::new(ModuleRibKind(module)));
+            this.ribs[ValueNS].push(Rib::new(ModuleRibKind(module)));
+            this.ribs[TypeNS].push(Rib::new(ModuleRibKind(module)));
             f(this)
         })
     }
@@ -2800,13 +2829,11 @@ impl<'a> Resolver<'a> {
     fn with_empty_ribs<T, F>(&mut self, f: F) -> T
         where F: FnOnce(&mut Resolver<'a>) -> T,
     {
-        let value_ribs = replace(&mut self.value_ribs, Vec::new());
-        let type_ribs = replace(&mut self.type_ribs, Vec::new());
+        let ribs = replace(&mut self.ribs, PerNS::<Vec<Rib>>::default());
         let label_ribs = replace(&mut self.label_ribs, Vec::new());
 
         let result = f(self);
-        self.value_ribs = value_ribs;
-        self.type_ribs = type_ribs;
+        self.ribs = ribs;
         self.label_ribs = label_ribs;
         result
     }
@@ -2858,7 +2885,7 @@ impl<'a> Resolver<'a> {
             return SuggestionType::Macro(format!("{}!", macro_name));
         }
 
-        let names = self.value_ribs
+        let names = self.ribs[ValueNS]
                     .iter()
                     .rev()
                     .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name));
@@ -2961,7 +2988,7 @@ impl<'a> Resolver<'a> {
                         } else {
                             let mut method_scope = false;
                             let mut is_static = false;
-                            self.value_ribs.iter().rev().all(|rib| {
+                            self.ribs[ValueNS].iter().rev().all(|rib| {
                                 method_scope = match rib.kind {
                                     MethodRibKind(is_static_) => {
                                         is_static = is_static_;
@@ -3072,10 +3099,10 @@ impl<'a> Resolver<'a> {
             ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
                 self.visit_expr(subexpression);
 
-                self.value_ribs.push(Rib::new(NormalRibKind));
+                self.ribs[ValueNS].push(Rib::new(NormalRibKind));
                 self.resolve_pattern(pattern, PatternSource::IfLet, &mut FxHashMap());
                 self.visit_block(if_block);
-                self.value_ribs.pop();
+                self.ribs[ValueNS].pop();
 
                 optional_else.as_ref().map(|expr| self.visit_expr(expr));
             }
@@ -3089,22 +3116,22 @@ impl<'a> Resolver<'a> {
 
             ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => {
                 self.visit_expr(subexpression);
-                self.value_ribs.push(Rib::new(NormalRibKind));
+                self.ribs[ValueNS].push(Rib::new(NormalRibKind));
                 self.resolve_pattern(pattern, PatternSource::WhileLet, &mut FxHashMap());
 
                 self.resolve_labeled_block(label, expr.id, block);
 
-                self.value_ribs.pop();
+                self.ribs[ValueNS].pop();
             }
 
             ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => {
                 self.visit_expr(subexpression);
-                self.value_ribs.push(Rib::new(NormalRibKind));
+                self.ribs[ValueNS].push(Rib::new(NormalRibKind));
                 self.resolve_pattern(pattern, PatternSource::For, &mut FxHashMap());
 
                 self.resolve_labeled_block(label, expr.id, block);
 
-                self.value_ribs.pop();
+                self.ribs[ValueNS].pop();
             }
 
             ExprKind::Field(ref subexpression, _) => {
@@ -3354,14 +3381,18 @@ impl<'a> Resolver<'a> {
         self.report_shadowing_errors();
         let mut reported_spans = FxHashSet();
 
-        for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors {
+        for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
             if !reported_spans.insert(span) { continue }
             let msg1 = format!("`{}` could resolve to the name imported here", name);
             let msg2 = format!("`{}` could also resolve to the name imported here", name);
             self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
                 .span_note(b1.span, &msg1)
                 .span_note(b2.span, &msg2)
-                .note(&format!("Consider adding an explicit import of `{}` to disambiguate", name))
+                .note(&if lexical || !b1.is_glob_import() {
+                    "macro-expanded macro imports do not shadow".to_owned()
+                } else {
+                    format!("consider adding an explicit import of `{}` to disambiguate", name)
+                })
                 .emit();
         }
 
@@ -3384,12 +3415,12 @@ impl<'a> Resolver<'a> {
 
     fn report_shadowing_errors(&mut self) {
         for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
-            self.resolve_macro_name(scope, name);
+            self.resolve_legacy_scope(scope, name, true);
         }
 
         let mut reported_errors = FxHashSet();
         for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
-            if self.resolve_macro_name(binding.parent, binding.name).is_some() &&
+            if self.resolve_legacy_scope(binding.parent, binding.name, false).is_some() &&
                reported_errors.insert((binding.name, binding.span)) {
                 let msg = format!("`{}` is already in scope", binding.name);
                 self.session.struct_span_err(binding.span, &msg)
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index f30c129c48f..524d491a464 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,14 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {Module, ModuleKind, Resolver};
+use {Module, ModuleKind, NameBinding, NameBindingKind, Resolver, AmbiguityError};
+use Namespace::{self, MacroNS};
+use ResolveResult::{Success, Indeterminate, Failed};
 use build_reduced_graph::BuildReducedGraphVisitor;
+use resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
 use rustc::hir::def::{Def, Export};
 use rustc::hir::map::{self, DefCollector};
+use rustc::ty;
 use std::cell::Cell;
 use std::rc::Rc;
-use syntax::ast;
+use syntax::ast::{self, Name};
 use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
 use syntax::ext::base::{NormalTT, SyntaxExtension};
@@ -27,7 +31,7 @@ use syntax::parse::token::intern;
 use syntax::ptr::P;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit::Visitor;
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 
 #[derive(Clone)]
 pub struct InvocationData<'a> {
@@ -83,6 +87,11 @@ pub struct LegacyBinding<'a> {
     pub span: Span,
 }
 
+pub enum MacroBinding<'a> {
+    Legacy(&'a LegacyBinding<'a>),
+    Modern(&'a NameBinding<'a>),
+}
+
 impl<'a> base::Resolver for Resolver<'a> {
     fn next_node_id(&mut self) -> ast::NodeId {
         self.session.next_node_id()
@@ -131,12 +140,14 @@ impl<'a> base::Resolver for Resolver<'a> {
         self.collect_def_ids(invocation, expansion);
 
         self.current_module = invocation.module.get();
+        self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
         let mut visitor = BuildReducedGraphVisitor {
             resolver: self,
             legacy_scope: LegacyScope::Invocation(invocation),
             expansion: mark,
         };
         expansion.visit_with(&mut visitor);
+        self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
         invocation.expansion.set(visitor.legacy_scope);
     }
 
@@ -177,18 +188,28 @@ impl<'a> base::Resolver for Resolver<'a> {
             index: DefIndex::new(self.macro_map.len()),
         };
         self.macro_map.insert(def_id, ext);
-        self.builtin_macros.insert(ident.name, def_id);
+        let binding = self.arenas.alloc_name_binding(NameBinding {
+            kind: NameBindingKind::Def(Def::Macro(def_id)),
+            span: DUMMY_SP,
+            vis: ty::Visibility::PrivateExternal,
+            expansion: Mark::root(),
+        });
+        self.builtin_macros.insert(ident.name, binding);
     }
 
     fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>) {
         self.macros_at_scope.insert(id, macros);
     }
 
+    fn resolve_imports(&mut self) {
+        ImportResolver { resolver: self }.resolve_imports()
+    }
+
     fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
         for i in 0..attrs.len() {
             let name = intern(&attrs[i].name());
-            match self.builtin_macros.get(&name) {
-                Some(&def_id) => match *self.get_macro(Def::Macro(def_id)) {
+            match self.builtin_macros.get(&name).cloned() {
+                Some(binding) => match *self.get_macro(binding) {
                     MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
                         return Some(attrs.remove(i))
                     }
@@ -212,25 +233,81 @@ impl<'a> base::Resolver for Resolver<'a> {
         if let LegacyScope::Expansion(parent) = invocation.legacy_scope.get() {
             invocation.legacy_scope.set(LegacyScope::simplify_expansion(parent));
         }
-        self.resolve_macro_name(invocation.legacy_scope.get(), name).ok_or_else(|| {
-            if force {
-                let msg = format!("macro undefined: '{}!'", name);
-                let mut err = self.session.struct_span_err(path.span, &msg);
-                self.suggest_macro_name(&name.as_str(), &mut err);
-                err.emit();
-                Determinacy::Determined
-            } else {
-                Determinacy::Undetermined
-            }
-        })
+
+        self.current_module = invocation.module.get();
+        let result = match self.resolve_legacy_scope(invocation.legacy_scope.get(), name, false) {
+            Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()),
+            Some(MacroBinding::Modern(binding)) => Ok(self.get_macro(binding)),
+            None => match self.resolve_in_item_lexical_scope(name, MacroNS, None) {
+                Some(binding) => Ok(self.get_macro(binding)),
+                None => return Err(if force {
+                    let msg = format!("macro undefined: '{}!'", name);
+                    let mut err = self.session.struct_span_err(path.span, &msg);
+                    self.suggest_macro_name(&name.as_str(), &mut err);
+                    err.emit();
+                    Determinacy::Determined
+                } else {
+                    Determinacy::Undetermined
+                }),
+            },
+        };
+
+        if self.use_extern_macros {
+            self.current_module.legacy_macro_resolutions.borrow_mut()
+                .push((scope, name, path.span));
+        }
+        result
     }
 }
 
 impl<'a> Resolver<'a> {
-    pub fn resolve_macro_name(&mut self, mut scope: LegacyScope<'a>, name: ast::Name)
-                              -> Option<Rc<SyntaxExtension>> {
+    // Resolve the name in the module's lexical scope, excluding non-items.
+    fn resolve_in_item_lexical_scope(&mut self,
+                                     name: Name,
+                                     ns: Namespace,
+                                     record_used: Option<Span>)
+                                     -> Option<&'a NameBinding<'a>> {
+        let mut module = self.current_module;
+        let mut potential_expanded_shadower = None;
+        loop {
+            // Since expanded macros may not shadow the lexical scope (enforced below),
+            // we can ignore unresolved invocations (indicated by the penultimate argument).
+            match self.resolve_name_in_module(module, name, ns, true, true, record_used) {
+                Success(binding) => {
+                    let span = match record_used {
+                        Some(span) => span,
+                        None => return Some(binding),
+                    };
+                    if let Some(shadower) = potential_expanded_shadower {
+                        self.ambiguity_errors.push(AmbiguityError {
+                            span: span, name: name, b1: shadower, b2: binding, lexical: true,
+                        });
+                        return Some(shadower);
+                    } else if binding.expansion == Mark::root() {
+                        return Some(binding);
+                    } else {
+                        potential_expanded_shadower = Some(binding);
+                    }
+                },
+                Indeterminate => return None,
+                Failed(..) => {}
+            }
+
+            match module.kind {
+                ModuleKind::Block(..) => module = module.parent.unwrap(),
+                ModuleKind::Def(..) => return potential_expanded_shadower,
+            }
+        }
+    }
+
+    pub fn resolve_legacy_scope(&mut self,
+                                mut scope: LegacyScope<'a>,
+                                name: Name,
+                                record_used: bool)
+                                -> Option<MacroBinding<'a>> {
         let mut possible_time_travel = None;
         let mut relative_depth: u32 = 0;
+        let mut binding = None;
         loop {
             scope = match scope {
                 LegacyScope::Empty => break,
@@ -249,25 +326,59 @@ impl<'a> Resolver<'a> {
                     relative_depth = relative_depth.saturating_sub(1);
                     invocation.legacy_scope.get()
                 }
-                LegacyScope::Binding(binding) => {
-                    if binding.name == name {
-                        if let Some(scope) = possible_time_travel {
-                            // Check for disallowed shadowing later
-                            self.lexical_macro_resolutions.push((name, scope));
-                        } else if relative_depth > 0 {
-                            self.disallowed_shadowing.push(binding);
+                LegacyScope::Binding(potential_binding) => {
+                    if potential_binding.name == name {
+                        if (!self.use_extern_macros || record_used) && relative_depth > 0 {
+                            self.disallowed_shadowing.push(potential_binding);
                         }
-                        return Some(binding.ext.clone());
+                        binding = Some(potential_binding);
+                        break
                     }
-                    binding.parent
+                    potential_binding.parent
                 }
             };
         }
 
-        if let Some(scope) = possible_time_travel {
-            self.lexical_macro_resolutions.push((name, scope));
+        let binding = match binding {
+            Some(binding) => MacroBinding::Legacy(binding),
+            None => match self.builtin_macros.get(&name).cloned() {
+                Some(binding) => MacroBinding::Modern(binding),
+                None => return None,
+            },
+        };
+
+        if !self.use_extern_macros {
+            if let Some(scope) = possible_time_travel {
+                // Check for disallowed shadowing later
+                self.lexical_macro_resolutions.push((name, scope));
+            }
+        }
+
+        Some(binding)
+    }
+
+    pub fn finalize_current_module_macro_resolutions(&mut self) {
+        let module = self.current_module;
+        for &(mark, name, span) in module.legacy_macro_resolutions.borrow().iter() {
+            let legacy_scope = self.invocations[&mark].legacy_scope.get();
+            let legacy_resolution = self.resolve_legacy_scope(legacy_scope, name, true);
+            let resolution = self.resolve_in_item_lexical_scope(name, MacroNS, Some(span));
+            let (legacy_resolution, resolution) = match (legacy_resolution, resolution) {
+                (Some(legacy_resolution), Some(resolution)) => (legacy_resolution, resolution),
+                _ => continue,
+            };
+            let (legacy_span, participle) = match legacy_resolution {
+                MacroBinding::Modern(binding) if binding.def() == resolution.def() => continue,
+                MacroBinding::Modern(binding) => (binding.span, "imported"),
+                MacroBinding::Legacy(binding) => (binding.span, "defined"),
+            };
+            let msg1 = format!("`{}` could resolve to the macro {} here", name, participle);
+            let msg2 = format!("`{}` could also resolve to the macro imported here", name);
+            self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
+                .span_note(legacy_span, &msg1)
+                .span_note(resolution.span, &msg2)
+                .emit();
         }
-        self.builtin_macros.get(&name).cloned().map(|def_id| self.get_macro(Def::Macro(def_id)))
     }
 
     fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 5d66caec31b..d0ce1acaadf 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -10,8 +10,8 @@
 
 use self::ImportDirectiveSubclass::*;
 
-use Module;
-use Namespace::{self, TypeNS, ValueNS};
+use {Module, PerNS};
+use Namespace::{self, TypeNS, MacroNS};
 use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding};
 use ResolveResult;
 use ResolveResult::*;
@@ -26,26 +26,20 @@ use rustc::hir::def::*;
 
 use syntax::ast::{Ident, NodeId, Name};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
+use syntax::ext::hygiene::Mark;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::Span;
 
 use std::cell::{Cell, RefCell};
 use std::mem;
 
-impl<'a> Resolver<'a> {
-    pub fn resolve_imports(&mut self) {
-        ImportResolver { resolver: self }.resolve_imports();
-    }
-}
-
 /// Contains data for specific types of import directives.
 #[derive(Clone, Debug)]
 pub enum ImportDirectiveSubclass<'a> {
     SingleImport {
         target: Name,
         source: Name,
-        value_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
-        type_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
+        result: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
     },
     GlobImport {
         is_prelude: bool,
@@ -55,17 +49,6 @@ pub enum ImportDirectiveSubclass<'a> {
     ExternCrate,
 }
 
-impl<'a> ImportDirectiveSubclass<'a> {
-    pub fn single(target: Name, source: Name) -> Self {
-        SingleImport {
-            target: target,
-            source: source,
-            type_result: Cell::new(Err(Undetermined)),
-            value_result: Cell::new(Err(Undetermined)),
-        }
-    }
-}
-
 /// One import directive.
 #[derive(Debug,Clone)]
 pub struct ImportDirective<'a> {
@@ -76,6 +59,7 @@ pub struct ImportDirective<'a> {
     pub subclass: ImportDirectiveSubclass<'a>,
     pub span: Span,
     pub vis: Cell<ty::Visibility>,
+    pub expansion: Mark,
 }
 
 impl<'a> ImportDirective<'a> {
@@ -158,6 +142,7 @@ impl<'a> Resolver<'a> {
                                   name: Name,
                                   ns: Namespace,
                                   allow_private_imports: bool,
+                                  ignore_unresolved_invocations: bool,
                                   record_used: Option<Span>)
                                   -> ResolveResult<&'a NameBinding<'a>> {
         self.populate_module_if_necessary(module);
@@ -191,66 +176,65 @@ impl<'a> Resolver<'a> {
             return resolution.binding.map(Success).unwrap_or(Failed(None));
         }
 
-        // If the resolution doesn't depend on glob definability, check privacy and return.
-        if let Some(result) = self.try_result(&resolution, ns) {
-            return result.and_then(|binding| {
-                if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) ||
-                   binding.is_extern_crate() { // c.f. issue #37020
-                    Success(binding)
-                } else {
-                    Failed(None)
-                }
-            });
-        }
+        let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
+            let usable =
+                this.is_accessible(binding.vis) && !is_disallowed_private_import(binding) ||
+                binding.is_extern_crate(); // c.f. issue #37020
+            if usable { Success(binding) } else { Failed(None) }
+        };
 
-        // Check if the globs are determined
-        for directive in module.globs.borrow().iter() {
-            if self.is_accessible(directive.vis.get()) {
-                if let Some(module) = directive.imported_module.get() {
-                    let result = self.resolve_name_in_module(module, name, ns, true, None);
-                    if let Indeterminate = result {
-                        return Indeterminate;
-                    }
-                } else {
-                    return Indeterminate;
-                }
+        // Items and single imports are not shadowable.
+        if let Some(binding) = resolution.binding {
+            if !binding.is_glob_import() {
+                return check_usable(self, binding);
             }
         }
 
-        Failed(None)
-    }
-
-    // Returns Some(the resolution of the name), or None if the resolution depends
-    // on whether more globs can define the name.
-    fn try_result(&mut self, resolution: &NameResolution<'a>, ns: Namespace)
-                  -> Option<ResolveResult<&'a NameBinding<'a>>> {
-        match resolution.binding {
-            Some(binding) if !binding.is_glob_import() =>
-                return Some(Success(binding)), // Items and single imports are not shadowable.
-            _ => {}
-        };
-
         // Check if a single import can still define the name.
         match resolution.single_imports {
-            SingleImports::AtLeastOne => return Some(Indeterminate),
+            SingleImports::AtLeastOne => return Indeterminate,
             SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
                 let module = match directive.imported_module.get() {
                     Some(module) => module,
-                    None => return Some(Indeterminate),
+                    None => return Indeterminate,
                 };
                 let name = match directive.subclass {
                     SingleImport { source, .. } => source,
                     _ => unreachable!(),
                 };
-                match self.resolve_name_in_module(module, name, ns, true, None) {
+                match self.resolve_name_in_module(module, name, ns, true, false, None) {
                     Failed(_) => {}
-                    _ => return Some(Indeterminate),
+                    _ => return Indeterminate,
                 }
             }
             SingleImports::MaybeOne(_) | SingleImports::None => {},
         }
 
-        resolution.binding.map(Success)
+        let no_unresolved_invocations =
+            ignore_unresolved_invocations || module.unresolved_invocations.borrow().is_empty();
+        match resolution.binding {
+            // In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`).
+            Some(binding) if no_unresolved_invocations || ns == MacroNS =>
+                return check_usable(self, binding),
+            None if no_unresolved_invocations => {}
+            _ => return Indeterminate,
+        }
+
+        // Check if the globs are determined
+        for directive in module.globs.borrow().iter() {
+            if self.is_accessible(directive.vis.get()) {
+                if let Some(module) = directive.imported_module.get() {
+                    let result = self.resolve_name_in_module(module, name, ns, true, false, None);
+                    if let Indeterminate = result {
+                        return Indeterminate;
+                    }
+                } else {
+                    return Indeterminate;
+                }
+            }
+        }
+
+        Failed(None)
     }
 
     // Add an import directive to the current module.
@@ -259,7 +243,8 @@ impl<'a> Resolver<'a> {
                                 subclass: ImportDirectiveSubclass<'a>,
                                 span: Span,
                                 id: NodeId,
-                                vis: ty::Visibility) {
+                                vis: ty::Visibility,
+                                expansion: Mark) {
         let current_module = self.current_module;
         let directive = self.arenas.alloc_import_directive(ImportDirective {
             parent: current_module,
@@ -269,15 +254,16 @@ impl<'a> Resolver<'a> {
             span: span,
             id: id,
             vis: Cell::new(vis),
+            expansion: expansion,
         });
 
         self.indeterminate_imports.push(directive);
         match directive.subclass {
             SingleImport { target, .. } => {
-                for &ns in &[ValueNS, TypeNS] {
-                    let mut resolution = self.resolution(current_module, target, ns).borrow_mut();
+                self.per_ns(|this, ns| {
+                    let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
                     resolution.single_imports.add_directive(directive);
-                }
+                });
             }
             // We don't add prelude imports to the globs since they only affect lexical scopes,
             // which are not relevant to import resolution.
@@ -312,6 +298,7 @@ impl<'a> Resolver<'a> {
             },
             span: directive.span,
             vis: vis,
+            expansion: directive.expansion,
         }
     }
 
@@ -324,28 +311,26 @@ impl<'a> Resolver<'a> {
         self.update_resolution(module, name, ns, |this, resolution| {
             if let Some(old_binding) = resolution.binding {
                 if binding.is_glob_import() {
-                    if !this.new_import_semantics || !old_binding.is_glob_import() {
+                    if !this.new_import_semantics {
                         resolution.duplicate_globs.push(binding);
+                    } else if !old_binding.is_glob_import() &&
+                              !(ns == MacroNS && old_binding.expansion != Mark::root()) {
                     } else if binding.def() != old_binding.def() {
-                        resolution.binding = Some(this.arenas.alloc_name_binding(NameBinding {
-                            kind: NameBindingKind::Ambiguity {
-                                b1: old_binding,
-                                b2: binding,
-                            },
-                            vis: if old_binding.vis.is_at_least(binding.vis, this) {
-                                old_binding.vis
-                            } else {
-                                binding.vis
-                            },
-                            span: old_binding.span,
-                        }));
+                        resolution.binding = Some(this.ambiguity(old_binding, binding));
                     } else if !old_binding.vis.is_at_least(binding.vis, this) {
                         // We are glob-importing the same item but with greater visibility.
                         resolution.binding = Some(binding);
                     }
                 } else if old_binding.is_glob_import() {
-                    resolution.duplicate_globs.push(old_binding);
-                    resolution.binding = Some(binding);
+                    if !this.new_import_semantics {
+                        resolution.duplicate_globs.push(old_binding);
+                        resolution.binding = Some(binding);
+                    } else if ns == MacroNS && binding.expansion != Mark::root() &&
+                              binding.def() != old_binding.def() {
+                        resolution.binding = Some(this.ambiguity(binding, old_binding));
+                    } else {
+                        resolution.binding = Some(binding);
+                    }
                 } else {
                     return Err(old_binding);
                 }
@@ -357,6 +342,16 @@ impl<'a> Resolver<'a> {
         })
     }
 
+    pub fn ambiguity(&mut self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
+                 -> &'a NameBinding<'a> {
+        self.arenas.alloc_name_binding(NameBinding {
+            kind: NameBindingKind::Ambiguity { b1: b1, b2: b2 },
+            vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis },
+            span: b1.span,
+            expansion: Mark::root(),
+        })
+    }
+
     // Use `f` to mutate the resolution of the name in the module.
     // If the resolution becomes a success, define it in the module's glob importers.
     fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T
@@ -393,10 +388,22 @@ impl<'a> Resolver<'a> {
 
         t
     }
+
+    // Define a "dummy" resolution containing a Def::Err as a placeholder for a
+    // failed resolution
+    fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
+        if let SingleImport { target, .. } = directive.subclass {
+            let dummy_binding = self.dummy_binding;
+            let dummy_binding = self.import(dummy_binding, directive);
+            self.per_ns(|this, ns| {
+                let _ = this.try_define(directive.parent, target, ns, dummy_binding.clone());
+            });
+        }
+    }
 }
 
-struct ImportResolver<'a, 'b: 'a> {
-    resolver: &'a mut Resolver<'b>,
+pub struct ImportResolver<'a, 'b: 'a> {
+    pub resolver: &'a mut Resolver<'b>,
 }
 
 impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> {
@@ -429,28 +436,21 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
     /// Resolves all imports for the crate. This method performs the fixed-
     /// point iteration.
-    fn resolve_imports(&mut self) {
-        let mut i = 0;
+    pub fn resolve_imports(&mut self) {
         let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
-
         while self.indeterminate_imports.len() < prev_num_indeterminates {
             prev_num_indeterminates = self.indeterminate_imports.len();
-            debug!("(resolving imports) iteration {}, {} imports left", i, prev_num_indeterminates);
-
-            let mut imports = Vec::new();
-            ::std::mem::swap(&mut imports, &mut self.indeterminate_imports);
-
-            for import in imports {
+            for import in mem::replace(&mut self.indeterminate_imports, Vec::new()) {
                 match self.resolve_import(&import) {
                     Failed(_) => self.determined_imports.push(import),
                     Indeterminate => self.indeterminate_imports.push(import),
                     Success(()) => self.determined_imports.push(import),
                 }
             }
-
-            i += 1;
         }
+    }
 
+    pub fn finalize_imports(&mut self) {
         for module in self.arenas.local_modules().iter() {
             self.finalize_resolutions_in(module);
         }
@@ -484,17 +484,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         }
     }
 
-    // Define a "dummy" resolution containing a Def::Err as a placeholder for a
-    // failed resolution
-    fn import_dummy_binding(&mut self, directive: &'b ImportDirective<'b>) {
-        if let SingleImport { target, .. } = directive.subclass {
-            let dummy_binding = self.dummy_binding;
-            let dummy_binding = self.import(dummy_binding, directive);
-            let _ = self.try_define(directive.parent, target, ValueNS, dummy_binding.clone());
-            let _ = self.try_define(directive.parent, target, TypeNS, dummy_binding);
-        }
-    }
-
     /// Attempts to resolve the given import. The return value indicates
     /// failure if we're certain the name does not exist, indeterminate if we
     /// don't know whether the name exists at the moment due to other
@@ -526,9 +515,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         };
 
         directive.imported_module.set(Some(module));
-        let (source, target, value_result, type_result) = match directive.subclass {
-            SingleImport { source, target, ref value_result, ref type_result } =>
-                (source, target, value_result, type_result),
+        let (source, target, result) = match directive.subclass {
+            SingleImport { source, target, ref result } => (source, target, result),
             GlobImport { .. } => {
                 self.resolve_glob_import(directive);
                 return Success(());
@@ -537,46 +525,45 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         };
 
         let mut indeterminate = false;
-        for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
-            if let Err(Undetermined) = result.get() {
-                result.set({
-                    match self.resolve_name_in_module(module, source, ns, false, None) {
+        self.per_ns(|this, ns| {
+            if let Err(Undetermined) = result[ns].get() {
+                result[ns].set({
+                    match this.resolve_name_in_module(module, source, ns, false, false, None) {
                         Success(binding) => Ok(binding),
                         Indeterminate => Err(Undetermined),
                         Failed(_) => Err(Determined),
                     }
                 });
             } else {
-                continue
+                return
             };
 
-            match result.get() {
+            match result[ns].get() {
                 Err(Undetermined) => indeterminate = true,
                 Err(Determined) => {
-                    self.update_resolution(directive.parent, target, ns, |_, resolution| {
+                    this.update_resolution(directive.parent, target, ns, |_, resolution| {
                         resolution.single_imports.directive_failed()
                     });
                 }
                 Ok(binding) if !binding.is_importable() => {
                     let msg = format!("`{}` is not directly importable", target);
-                    struct_span_err!(self.session, directive.span, E0253, "{}", &msg)
+                    struct_span_err!(this.session, directive.span, E0253, "{}", &msg)
                         .span_label(directive.span, &format!("cannot be imported directly"))
                         .emit();
                     // Do not import this illegal binding. Import a dummy binding and pretend
                     // everything is fine
-                    self.import_dummy_binding(directive);
-                    return Success(());
+                    this.import_dummy_binding(directive);
                 }
                 Ok(binding) => {
-                    let imported_binding = self.import(binding, directive);
-                    let conflict = self.try_define(directive.parent, target, ns, imported_binding);
+                    let imported_binding = this.import(binding, directive);
+                    let conflict = this.try_define(directive.parent, target, ns, imported_binding);
                     if let Err(old_binding) = conflict {
-                        let binding = &self.import(binding, directive);
-                        self.report_conflict(directive.parent, target, ns, binding, old_binding);
+                        let binding = &this.import(binding, directive);
+                        this.report_conflict(directive.parent, target, ns, binding, old_binding);
                     }
                 }
             }
-        }
+        });
 
         if indeterminate { Indeterminate } else { Success(()) }
     }
@@ -604,9 +591,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             },
         };
 
-        let (name, value_result, type_result) = match directive.subclass {
-            SingleImport { source, ref value_result, ref type_result, .. } =>
-                (source, value_result.get(), type_result.get()),
+        let (name, result) = match directive.subclass {
+            SingleImport { source, ref result, .. } => (source, result),
             GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
                 // Importing a module into itself is not allowed.
                 let msg = "Cannot glob-import a module into itself.".into();
@@ -624,21 +610,27 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             _ => unreachable!(),
         };
 
-        for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
-            if let Ok(binding) = result {
-                if self.record_use(name, ns, binding, directive.span) {
-                    self.resolution(module, name, ns).borrow_mut().binding =
-                        Some(self.dummy_binding);
+        let mut all_ns_err = true;
+        self.per_ns(|this, ns| {
+            if let Ok(binding) = result[ns].get() {
+                all_ns_err = false;
+                if this.record_use(name, ns, binding, directive.span) {
+                    this.resolution(module, name, ns).borrow_mut().binding =
+                        Some(this.dummy_binding);
                 }
             }
-        }
+        });
 
-        if value_result.is_err() && type_result.is_err() {
-            let (value_result, type_result);
-            value_result = self.resolve_name_in_module(module, name, ValueNS, false, Some(span));
-            type_result = self.resolve_name_in_module(module, name, TypeNS, false, Some(span));
+        if all_ns_err {
+            let mut all_ns_failed = true;
+            self.per_ns(|this, ns| {
+                match this.resolve_name_in_module(module, name, ns, false, false, Some(span)) {
+                    Success(_) => all_ns_failed = false,
+                    _ => {}
+                }
+            });
 
-            return if let (Failed(_), Failed(_)) = (value_result, type_result) {
+            return if all_ns_failed {
                 let resolutions = module.resolutions.borrow();
                 let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| {
                     if *n == name { return None; } // Never suggest the same name
@@ -666,64 +658,49 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             }
         }
 
-        let session = self.session;
-        let reexport_error = || {
-            let msg = format!("`{}` is private, and cannot be reexported", name);
-            let note_msg =
-                format!("consider marking `{}` as `pub` in the imported module", name);
-            struct_span_err!(session, directive.span, E0364, "{}", &msg)
-                .span_note(directive.span, &note_msg)
-                .emit();
-        };
-
-        let extern_crate_lint = || {
-            let msg = format!("extern crate `{}` is private, and cannot be reexported \
-                               (error E0364), consider declaring with `pub`",
-                               name);
-            session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
-        };
-
-        match (value_result, type_result) {
-            // All namespaces must be re-exported with extra visibility for an error to occur.
-            (Ok(value_binding), Ok(type_binding)) => {
+        let mut reexport_error = None;
+        let mut any_successful_reexport = false;
+        self.per_ns(|this, ns| {
+            if let Ok(binding) = result[ns].get() {
                 let vis = directive.vis.get();
-                if !value_binding.pseudo_vis().is_at_least(vis, self) &&
-                   !type_binding.pseudo_vis().is_at_least(vis, self) {
-                    reexport_error();
-                } else if type_binding.is_extern_crate() &&
-                          !type_binding.vis.is_at_least(vis, self) {
-                    extern_crate_lint();
-                }
-            }
-
-            (Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
-                reexport_error();
-            }
-
-            (_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
-                if binding.is_extern_crate() {
-                    extern_crate_lint();
+                if !binding.pseudo_vis().is_at_least(vis, this) {
+                    reexport_error = Some((ns, binding));
                 } else {
-                    struct_span_err!(self.session, directive.span, E0365,
-                                     "`{}` is private, and cannot be reexported", name)
-                        .span_label(directive.span, &format!("reexport of private `{}`", name))
-                        .note(&format!("consider declaring type or module `{}` with `pub`", name))
-                        .emit();
+                    any_successful_reexport = true;
                 }
             }
+        });
 
-            _ => {}
+        // All namespaces must be re-exported with extra visibility for an error to occur.
+        if !any_successful_reexport {
+            let (ns, binding) = reexport_error.unwrap();
+            if ns == TypeNS && binding.is_extern_crate() {
+                let msg = format!("extern crate `{}` is private, and cannot be reexported \
+                                   (error E0364), consider declaring with `pub`",
+                                   name);
+                self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
+            } else if ns == TypeNS {
+                struct_span_err!(self.session, directive.span, E0365,
+                                 "`{}` is private, and cannot be reexported", name)
+                    .span_label(directive.span, &format!("reexport of private `{}`", name))
+                    .note(&format!("consider declaring type or module `{}` with `pub`", name))
+                    .emit();
+            } else {
+                let msg = format!("`{}` is private, and cannot be reexported", name);
+                let note_msg =
+                    format!("consider marking `{}` as `pub` in the imported module", name);
+                struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
+                    .span_note(directive.span, &note_msg)
+                    .emit();
+            }
         }
 
         // Record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
-        let def = match type_result.ok().map(NameBinding::def) {
-            Some(def) => def,
-            None => value_result.ok().map(NameBinding::def).unwrap(),
-        };
-        let path_resolution = PathResolution::new(def);
-        self.def_map.insert(directive.id, path_resolution);
+        self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() {
+            this.def_map.entry(directive.id).or_insert(PathResolution::new(binding.def()));
+        });
 
         debug!("(resolving single import) successfully resolved import");
         return Success(());
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index b4ac576f57a..7f66b060052 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -524,6 +524,7 @@ pub trait Resolver {
     fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
     fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
 
+    fn resolve_imports(&mut self);
     fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
     fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy>;
@@ -547,6 +548,7 @@ impl Resolver for DummyResolver {
     fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
     fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
 
+    fn resolve_imports(&mut self) {}
     fn find_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
     fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
                      -> Result<Rc<SyntaxExtension>, Determinacy> {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 877b312539f..8e0c3ce8448 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -222,6 +222,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         self.cx.current_expansion.depth = 0;
 
         let (expansion, mut invocations) = self.collect_invocations(expansion);
+        self.resolve_imports();
         invocations.reverse();
 
         let mut expansions = Vec::new();
@@ -230,9 +231,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         loop {
             let invoc = if let Some(invoc) = invocations.pop() {
                 invoc
-            } else if undetermined_invocations.is_empty() {
-                break
             } else {
+                self.resolve_imports();
+                if undetermined_invocations.is_empty() { break }
                 invocations = mem::replace(&mut undetermined_invocations, Vec::new());
                 force = !mem::replace(&mut progress, false);
                 continue
@@ -292,6 +293,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         expansion.fold_with(&mut placeholder_expander)
     }
 
+    fn resolve_imports(&mut self) {
+        if self.monotonic {
+            let err_count = self.cx.parse_sess.span_diagnostic.err_count();
+            self.cx.resolver.resolve_imports();
+            self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count;
+        }
+    }
+
     fn collect_invocations(&mut self, expansion: Expansion) -> (Expansion, Vec<Invocation>) {
         let result = {
             let mut collector = InvocationCollector {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 27f720b7609..ea66fdc31cf 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -314,6 +314,8 @@ declare_features! (
 
     // Allows #[link(..., cfg(..))]
     (active, link_cfg, "1.14.0", Some(37406)),
+
+    (active, use_extern_macros, "1.15.0", Some(35896)),
 );
 
 declare_features! (
diff --git a/src/test/compile-fail/blind-item-block-item-shadow.rs b/src/test/compile-fail/blind-item-block-item-shadow.rs
index a26b9e3c7aa..2d53aee39e9 100644
--- a/src/test/compile-fail/blind-item-block-item-shadow.rs
+++ b/src/test/compile-fail/blind-item-block-item-shadow.rs
@@ -14,6 +14,6 @@ fn main() {
     {
         struct Bar;
         use foo::Bar;
-        //~^ ERROR a value named `Bar` has already been defined in this block
+        //~^ ERROR a type named `Bar` has already been defined in this block
     }
 }
diff --git a/src/test/compile-fail/double-type-import.rs b/src/test/compile-fail/double-type-import.rs
index e51ef5e32e8..760612c05ce 100644
--- a/src/test/compile-fail/double-type-import.rs
+++ b/src/test/compile-fail/double-type-import.rs
@@ -11,7 +11,7 @@
 mod foo {
     pub use self::bar::X;
     use self::bar::X;
-    //~^ ERROR a value named `X` has already been imported in this module
+    //~^ ERROR a type named `X` has already been imported in this module
 
     mod bar {
         pub struct X;
diff --git a/src/test/compile-fail/imports/auxiliary/two_macros.rs b/src/test/compile-fail/imports/auxiliary/two_macros.rs
new file mode 100644
index 00000000000..2ac8e3ef983
--- /dev/null
+++ b/src/test/compile-fail/imports/auxiliary/two_macros.rs
@@ -0,0 +1,15 @@
+// Copyright 2016 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.
+
+#[macro_export]
+macro_rules! m { ($($t:tt)*) => { $($t)* } }
+
+#[macro_export]
+macro_rules! n { ($($t:tt)*) => { $($t)* } }
diff --git a/src/test/compile-fail/imports/duplicate.rs b/src/test/compile-fail/imports/duplicate.rs
index fb61bb8e489..faf85a523e8 100644
--- a/src/test/compile-fail/imports/duplicate.rs
+++ b/src/test/compile-fail/imports/duplicate.rs
@@ -46,9 +46,9 @@ mod g {
 fn main() {
     e::foo();
     f::foo(); //~ ERROR `foo` is ambiguous
-              //~| NOTE Consider adding an explicit import of `foo` to disambiguate
+              //~| NOTE consider adding an explicit import of `foo` to disambiguate
     g::foo(); //~ ERROR `foo` is ambiguous
-              //~| NOTE Consider adding an explicit import of `foo` to disambiguate
+              //~| NOTE consider adding an explicit import of `foo` to disambiguate
 }
 
 mod ambiguous_module_errors {
diff --git a/src/test/compile-fail/imports/macros.rs b/src/test/compile-fail/imports/macros.rs
new file mode 100644
index 00000000000..c11d2aab7c6
--- /dev/null
+++ b/src/test/compile-fail/imports/macros.rs
@@ -0,0 +1,55 @@
+// Copyright 2016 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.
+
+// aux-build:two_macros.rs
+
+#![feature(item_like_imports, use_extern_macros)]
+
+extern crate two_macros; // two identity macros `m` and `n`
+
+mod foo {
+    pub use two_macros::n as m;
+}
+
+mod m1 {
+    m!(use two_macros::*;);
+    use foo::m; // This shadows the glob import
+}
+
+mod m2 {
+    use two_macros::*; //~ NOTE could also resolve
+    m! { //~ ERROR ambiguous
+         //~| NOTE macro-expanded macro imports do not shadow
+        use foo::m; //~ NOTE could resolve to the name imported here
+                    //~^^^ NOTE in this expansion
+    }
+}
+
+mod m3 {
+    use two_macros::m; //~ NOTE could also resolve
+    fn f() {
+        use two_macros::n as m; // This shadows the above import
+        m!();
+    }
+
+    fn g() {
+        m! { //~ ERROR ambiguous
+             //~| NOTE macro-expanded macro imports do not shadow
+            use two_macros::n as m; //~ NOTE could resolve to the name imported here
+                                    //~^^^ NOTE in this expansion
+        }
+    }
+}
+
+mod m4 {
+    macro_rules! m { () => {} } //~ NOTE could resolve to the macro defined here
+    use two_macros::m; //~ NOTE could also resolve to the macro imported here
+    m!(); //~ ERROR ambiguous
+}