diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 5917a1a0d1759..6816789cf2846 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 { - let def_id = match def { - Def::Macro(def_id) => def_id, + pub fn get_macro(&mut self, binding: &'b NameBinding<'b>) -> Rc { + 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 af72977024253..a3a60e4f6d754 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -540,6 +540,7 @@ pub enum Namespace { pub struct PerNS { value_ns: T, type_ns: T, + macro_ns: Option, } impl ::std::ops::Index for PerNS { @@ -548,7 +549,7 @@ impl ::std::ops::Index for PerNS { match ns { ValueNS => &self.value_ns, TypeNS => &self.type_ns, - MacroNS => unreachable!(), + MacroNS => self.macro_ns.as_ref().unwrap(), } } } @@ -558,7 +559,7 @@ impl ::std::ops::IndexMut for PerNS { 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 { 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 { } impl ResolveResult { - fn and_then ResolveResult>(self, f: F) -> ResolveResult { - match self { - Failed(msg) => Failed(msg), - Indeterminate => Indeterminate, - Success(t) => f(t), - } - } - fn success(self) -> Option { match self { Success(t) => Some(t), @@ -825,6 +818,7 @@ pub struct ModuleS<'a> { normal_ancestor_id: Option, resolutions: RefCell>>>, + legacy_macro_resolutions: RefCell>, // Macro invocations that can expand into items in this module. unresolved_invocations: RefCell>, @@ -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, 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> { fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>) -> Option> { - 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::>(); - 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::>(); - 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 2d434d660ea5a..56d76272e235a 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> { + // 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, + ) -> 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> { 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 f04f3bf45ee93..d0ce1acaadf62 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) -> 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>> { - 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(&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 27f720b760998..ea66fdc31cf08 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 fb61bb8e489be..faf85a523e8fb 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 {