about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-10 10:29:36 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-17 08:08:06 +0000
commit9c886500801fe7cbdc4c9a7dfd2294df8b10db8b (patch)
tree2d3d40551f32cb034dcbf023547206fdb1f451e1
parentb25c063caa5e4ab8202527e3cfcfe04196e0836f (diff)
downloadrust-9c886500801fe7cbdc4c9a7dfd2294df8b10db8b.tar.gz
rust-9c886500801fe7cbdc4c9a7dfd2294df8b10db8b.zip
Add feature `use_extern_macros`.
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs12
-rw-r--r--src/librustc_resolve/lib.rs80
-rw-r--r--src/librustc_resolve/macros.rs150
-rw-r--r--src/librustc_resolve/resolve_imports.rs125
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/test/compile-fail/imports/duplicate.rs4
6 files changed, 238 insertions, 135 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 5917a1a0d17..6816789cf28 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -504,9 +504,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) {
@@ -579,7 +581,7 @@ impl<'b> Resolver<'b> {
             });
         } 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, span, allow_shadowing);
                 } else {
@@ -589,7 +591,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 {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index af729770242..a3a60e4f6d7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -540,6 +540,7 @@ pub enum Namespace {
 pub struct PerNS<T> {
     value_ns: T,
     type_ns: T,
+    macro_ns: Option<T>,
 }
 
 impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
@@ -548,7 +549,7 @@ impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
         match ns {
             ValueNS => &self.value_ns,
             TypeNS => &self.type_ns,
-            MacroNS => unreachable!(),
+            MacroNS => self.macro_ns.as_ref().unwrap(),
         }
     }
 }
@@ -558,7 +559,7 @@ impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
         match ns {
             ValueNS => &mut self.value_ns,
             TypeNS => &mut self.type_ns,
-            MacroNS => unreachable!(),
+            MacroNS => self.macro_ns.as_mut().unwrap(),
         }
     }
 }
@@ -675,7 +676,7 @@ impl<'a> Visitor for Resolver<'a> {
 
 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.
@@ -683,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),
@@ -825,6 +818,7 @@ 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>>,
@@ -852,6 +846,7 @@ 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()),
@@ -943,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>,
 }
@@ -1001,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,
         }
     }
@@ -1136,6 +1132,7 @@ 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,
@@ -1300,6 +1297,7 @@ impl<'a> Resolver<'a> {
             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(),
 
@@ -1336,6 +1334,7 @@ impl<'a> Resolver<'a> {
                 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,
@@ -1365,6 +1364,10 @@ impl<'a> Resolver<'a> {
         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,
+            },
         }
     }
 
@@ -1403,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
@@ -1438,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)
@@ -1456,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);
@@ -1613,7 +1617,7 @@ impl<'a> Resolver<'a> {
 
             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));
@@ -1622,7 +1626,7 @@ 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;
@@ -1717,6 +1721,7 @@ impl<'a> Resolver<'a> {
             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;
@@ -2221,6 +2226,7 @@ impl<'a> Resolver<'a> {
             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.ribs[ValueNS].push(Rib::new(NormalRibKind));
         }
@@ -2754,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));
@@ -2763,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)
     }
 
@@ -2782,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));
@@ -2795,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)
     }
 
@@ -3383,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();
         }
 
@@ -3413,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 2d434d660ea..56d76272e23 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {Module, ModuleKind, NameBinding, NameBindingKind, 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};
@@ -17,7 +19,7 @@ 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};
@@ -85,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()
@@ -140,6 +147,7 @@ impl<'a> base::Resolver for Resolver<'a> {
             expansion: mark,
         };
         expansion.visit_with(&mut visitor);
+        self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
         invocation.expansion.set(visitor.legacy_scope);
     }
 
@@ -201,7 +209,7 @@ impl<'a> base::Resolver for Resolver<'a> {
         for i in 0..attrs.len() {
             let name = intern(&attrs[i].name());
             match self.builtin_macros.get(&name).cloned() {
-                Some(binding) => match *self.get_macro(binding.def()) {
+                Some(binding) => match *self.get_macro(binding) {
                     MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
                         return Some(attrs.remove(i))
                     }
@@ -225,25 +233,77 @@ 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: ast::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,
@@ -262,25 +322,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(|binding| self.get_macro(binding.def()))
     }
 
     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 f04f3bf45ee..d0ce1acaadf 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -11,7 +11,7 @@
 use self::ImportDirectiveSubclass::*;
 
 use {Module, PerNS};
-use Namespace::{self, TypeNS};
+use Namespace::{self, TypeNS, MacroNS};
 use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding};
 use ResolveResult;
 use ResolveResult::*;
@@ -142,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);
@@ -175,70 +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, module, 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>, module: Module<'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 => {},
         }
 
-        if !module.unresolved_invocations.borrow().is_empty() {
-            return Some(Indeterminate);
+        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,
         }
 
-        resolution.binding.map(Success)
+        // 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.
@@ -315,29 +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,
-                            expansion: Mark::root(),
-                        }));
+                        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);
                 }
@@ -349,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
@@ -525,7 +528,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         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, None) {
+                    match this.resolve_name_in_module(module, source, ns, false, false, None) {
                         Success(binding) => Ok(binding),
                         Indeterminate => Err(Undetermined),
                         Failed(_) => Err(Determined),
@@ -621,7 +624,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         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, Some(span)) {
+                match this.resolve_name_in_module(module, name, ns, false, false, Some(span)) {
                     Success(_) => all_ns_failed = false,
                     _ => {}
                 }
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/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 {