diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1a56f6a056d38..1443704a0d647 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -52,6 +52,7 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) { vis: self.1, span: self.2, expansion: self.3, + is_macro_export: false, }) } } @@ -63,6 +64,19 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { vis: self.1, span: self.2, expansion: self.3, + is_macro_export: false, + }) + } +} + +impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, bool) { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { + arenas.alloc_name_binding(NameBinding { + kind: NameBindingKind::Def(self.0), + vis: self.1, + span: self.2, + expansion: self.3, + is_macro_export: self.4, }) } } @@ -674,8 +688,7 @@ impl<'a> Resolver<'a> { } else { for (name, span) in legacy_imports.imports { let ident = Ident::with_empty_ctxt(name); - let result = self.resolve_ident_in_module(module, ident, MacroNS, - false, false, span); + let result = self.resolve_ident_in_module(module, ident, MacroNS, false, span); if let Ok(binding) = result { let directive = macro_use_directive(span); self.potentially_unused_imports.push(directive); @@ -743,6 +756,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { let mark = id.placeholder_to_mark(); self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); + self.resolver.unresolved_invocations_macro_export.insert(mark); let invocation = self.resolver.invocations[&mark]; invocation.module.set(self.resolver.current_module); invocation.legacy_scope.set(self.legacy_scope); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7e7106489db46..3f1043e502883 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1100,6 +1100,7 @@ impl<'a> fmt::Debug for ModuleData<'a> { pub struct NameBinding<'a> { kind: NameBindingKind<'a>, expansion: Mark, + is_macro_export: bool, span: Span, vis: ty::Visibility, } @@ -1141,12 +1142,20 @@ struct UseError<'a> { better: bool, } +#[derive(Clone, Copy, Debug)] +enum AmbiguityErrorKind { + RecordUse, + ResolveLexical, + ResolveInModule, +} + struct AmbiguityError<'a> { span: Span, name: Name, lexical: bool, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>, + kind: AmbiguityErrorKind, } impl<'a> NameBinding<'a> { @@ -1393,7 +1402,6 @@ pub struct Resolver<'a> { macro_map: FxHashMap>, macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, - macro_exports: Vec, pub whitelisted_legacy_custom_derives: Vec, pub found_unresolved_macro: bool, @@ -1426,6 +1434,9 @@ pub struct Resolver<'a> { /// Only supposed to be used by rustdoc, otherwise should be false. pub ignore_extern_prelude_feature: bool, + + /// Macro invocations in the whole crate that can expand into a `#[macro_export] macro_rules`. + unresolved_invocations_macro_export: FxHashSet, } /// Nothing really interesting here, it just provides memory for the rest of the crate. @@ -1703,6 +1714,7 @@ impl<'a> Resolver<'a> { expansion: Mark::root(), span: DUMMY_SP, vis: ty::Visibility::Public, + is_macro_export: false, }), crate_loader, @@ -1711,7 +1723,6 @@ impl<'a> Resolver<'a> { all_macros: FxHashMap(), lexical_macro_resolutions: Vec::new(), macro_map: FxHashMap(), - macro_exports: Vec::new(), invocations, macro_defs, local_macro_def_scopes: FxHashMap(), @@ -1726,6 +1737,7 @@ impl<'a> Resolver<'a> { current_type_ascription: Vec::new(), injected_crate: None, ignore_extern_prelude_feature: false, + unresolved_invocations_macro_export: FxHashSet(), } } @@ -1797,6 +1809,7 @@ impl<'a> Resolver<'a> { NameBindingKind::Ambiguity { b1, b2 } => { self.ambiguity_errors.push(AmbiguityError { span, name: ident.name, lexical: false, b1, b2, + kind: AmbiguityErrorKind::RecordUse }); true } @@ -1957,7 +1970,6 @@ impl<'a> Resolver<'a> { module: Module<'a>, mut ident: Ident, ns: Namespace, - ignore_unresolved_invocations: bool, record_used: bool, span: Span) -> Result<&'a NameBinding<'a>, Determinacy> { @@ -1967,7 +1979,7 @@ impl<'a> Resolver<'a> { self.current_module = self.macro_def_scope(def); } let result = self.resolve_ident_in_module_unadjusted( - module, ident, ns, ignore_unresolved_invocations, record_used, span, + module, ident, ns, false, record_used, span, ); self.current_module = orig_current_module; result @@ -2460,7 +2472,7 @@ impl<'a> Resolver<'a> { // If there is a TraitRef in scope for an impl, then the method must be in the // trait. if let Some((module, _)) = self.current_trait_ref { - if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() { + if self.resolve_ident_in_module(module, ident, ns, false, span).is_err() { let path = &self.current_trait_ref.as_ref().unwrap().1.path; resolve_error(self, span, err(ident.name, &path_names_to_string(path))); } @@ -3410,7 +3422,7 @@ impl<'a> Resolver<'a> { } let binding = if let Some(module) = module { - self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span) + self.resolve_ident_in_module(module, ident, ns, record_used, path_span) } else if opt_ns == Some(MacroNS) { self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span) .map(MacroBinding::binding) @@ -3704,7 +3716,7 @@ impl<'a> Resolver<'a> { // Look for associated items in the current trait. if let Some((module, _)) = self.current_trait_ref { if let Ok(binding) = - self.resolve_ident_in_module(module, ident, ns, false, false, module.span) { + self.resolve_ident_in_module(module, ident, ns, false, module.span) { let def = binding.def(); if filter_fn(def) { return Some(if self.has_self.contains(&def.def_id()) { @@ -4017,7 +4029,7 @@ impl<'a> Resolver<'a> { let mut found_traits = Vec::new(); // Look for the current trait. if let Some((module, _)) = self.current_trait_ref { - if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() { + if self.resolve_ident_in_module(module, ident, ns, false, module.span).is_ok() { let def_id = module.def_id().unwrap(); found_traits.push(TraitCandidate { def_id: def_id, import_id: None }); } @@ -4290,7 +4302,7 @@ impl<'a> Resolver<'a> { self.report_proc_macro_import(krate); let mut reported_spans = FxHashSet(); - for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors { + for &AmbiguityError { span, name, b1, b2, lexical, kind } in &self.ambiguity_errors { if !reported_spans.insert(span) { continue } let participle = |binding: &NameBinding| { if binding.is_import() { "imported" } else { "defined" } @@ -4307,7 +4319,8 @@ impl<'a> Resolver<'a> { if b1.is_import() { "imports" } else { "items" }) }; - let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name); + let mut err = struct_span_err!(self.session, span, E0659, + "`{}` is ambiguous {:?}", name, kind); err.span_note(b1.span, &msg1); match b2.def() { Def::Macro(..) if b2.span.is_dummy() => diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ef769302dafe6..7dd56ec7f5791 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {AmbiguityError, CrateLint, Resolver, ResolutionError, resolve_error}; +use {AmbiguityError, AmbiguityErrorKind, CrateLint, Resolver, ResolutionError, resolve_error}; use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult}; use Namespace::{self, MacroNS}; use build_reduced_graph::BuildReducedGraphVisitor; use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace}; -use rustc::hir::def::{Def, Export}; +use rustc::hir::def::Def; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; use syntax::ast::{self, Name, Ident}; @@ -193,7 +193,9 @@ impl<'a> base::Resolver for Resolver<'a> { self.current_module = invocation.module.get(); self.current_module.unresolved_invocations.borrow_mut().remove(&mark); + self.unresolved_invocations_macro_export.remove(&mark); self.current_module.unresolved_invocations.borrow_mut().extend(derives); + self.unresolved_invocations_macro_export.extend(derives); for &derive in derives { self.invocations.insert(derive, invocation); } @@ -219,6 +221,7 @@ impl<'a> base::Resolver for Resolver<'a> { span: DUMMY_SP, vis: ty::Visibility::Invisible, expansion: Mark::root(), + is_macro_export: false, }); self.global_macros.insert(ident.name, binding); } @@ -552,11 +555,12 @@ impl<'a> Resolver<'a> { b1: shadower, b2: binding, lexical: true, + kind: AmbiguityErrorKind::ResolveLexical, }); return potential_illegal_shadower; } } - if binding.expansion != Mark::root() || + if binding.expansion != Mark::root() || binding.is_macro_export || (binding.is_glob_import() && module.unwrap().def().is_some()) { potential_illegal_shadower = result; } else { @@ -666,12 +670,16 @@ impl<'a> Resolver<'a> { match (legacy_resolution, resolution) { (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => { - let msg1 = format!("`{}` could refer to the macro defined here", ident); - let msg2 = format!("`{}` could also refer to the macro imported here", ident); - self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident)) - .span_note(legacy_binding.span, &msg1) - .span_note(binding.span, &msg2) - .emit(); + if legacy_binding.def_id != binding.def_ignoring_ambiguity().def_id() { + let msg1 = + format!("`{}` could refer to the macro defined here", ident); + let msg2 = + format!("`{}` could also refer to the macro imported here", ident); + self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident)) + .span_note(legacy_binding.span, &msg1) + .span_note(binding.span, &msg2) + .emit(); + } }, (None, Err(_)) => { assert!(def.is_none()); @@ -802,12 +810,9 @@ impl<'a> Resolver<'a> { let def = Def::Macro(def_id, MacroKind::Bang); self.all_macros.insert(ident.name, def); if attr::contains_name(&item.attrs, "macro_export") { - self.macro_exports.push(Export { - ident: ident.modern(), - def: def, - vis: ty::Visibility::Public, - span: item.span, - }); + let module = self.graph_root; + let vis = ty::Visibility::Public; + self.define(module, ident, MacroNS, (def, vis, item.span, expansion, false)); } else { self.unused_macros.insert(def_id); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 4012ecbe3c100..5f9f7fbe561bb 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -10,7 +10,7 @@ use self::ImportDirectiveSubclass::*; -use {AmbiguityError, CrateLint, Module, PerNS}; +use {AmbiguityError, AmbiguityErrorKind, CrateLint, Module, PerNS}; use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; use Resolver; @@ -18,14 +18,13 @@ use {names_to_string, module_to_string}; use {resolve_error, ResolutionError}; use rustc::ty; -use rustc::lint::builtin::BuiltinLintDiagnostics; -use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE}; +use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::def::*; use rustc::session::DiagnosticMessageId; -use rustc::util::nodemap::{FxHashMap, FxHashSet}; +use rustc::util::nodemap::FxHashSet; -use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID}; +use syntax::ast::{Ident, Name, NodeId}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; use syntax::symbol::keywords; @@ -183,6 +182,7 @@ impl<'a> Resolver<'a> { record_used: bool, path_span: Span) -> Result<&'a NameBinding<'a>, Determinacy> { + let restricted_shadowing = restricted_shadowing || ns == MacroNS; self.populate_module_if_necessary(module); let resolution = self.resolution(module, ident, ns) @@ -195,7 +195,7 @@ impl<'a> Resolver<'a> { let name = ident.name; // Forbid expanded shadowing to avoid time travel. if restricted_shadowing && - binding.expansion != Mark::root() && + (binding.expansion != Mark::root() || binding.is_macro_export) && ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing binding.def() != shadowed_glob.def() { self.ambiguity_errors.push(AmbiguityError { @@ -204,6 +204,7 @@ impl<'a> Resolver<'a> { lexical: false, b1: binding, b2: shadowed_glob, + kind: AmbiguityErrorKind::ResolveInModule, }); } } @@ -241,7 +242,7 @@ impl<'a> Resolver<'a> { SingleImport { source, .. } => source, _ => unreachable!(), }; - match this.resolve_ident_in_module(module, ident, ns, false, false, path_span) { + match this.resolve_ident_in_module(module, ident, ns, false, path_span) { Err(Determined) => {} _ => return false, } @@ -282,7 +283,7 @@ impl<'a> Resolver<'a> { restricted_shadowing || 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 => + Some(binding) if no_unresolved_invocations => return check_usable(self, binding), None if no_unresolved_invocations => {} _ => return Err(Undetermined), @@ -383,6 +384,7 @@ impl<'a> Resolver<'a> { span: directive.span, vis, expansion: directive.expansion, + is_macro_export: false, }) } @@ -397,7 +399,8 @@ impl<'a> Resolver<'a> { if let Some(old_binding) = resolution.binding { if binding.is_glob_import() { if !old_binding.is_glob_import() && - !(ns == MacroNS && old_binding.expansion != Mark::root()) { + !(ns == MacroNS && (old_binding.expansion != Mark::root() || + old_binding.is_macro_export)) { resolution.shadows_glob = Some(binding); } else if binding.def() != old_binding.def() { resolution.binding = Some(this.ambiguity(old_binding, binding)); @@ -406,7 +409,8 @@ impl<'a> Resolver<'a> { resolution.binding = Some(binding); } } else if old_binding.is_glob_import() { - if ns == MacroNS && binding.expansion != Mark::root() && + if ns == MacroNS && (binding.expansion != Mark::root() || + binding.is_macro_export) && binding.def() != old_binding.def() { resolution.binding = Some(this.ambiguity(binding, old_binding)); } else { @@ -431,6 +435,7 @@ impl<'a> Resolver<'a> { vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis }, span: b1.span, expansion: Mark::root(), + is_macro_export: false, }) } @@ -627,7 +632,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { source, ns, false, - false, directive.span)); } else { return @@ -726,6 +730,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { vis: directive.vis.get(), span: directive.span, expansion: directive.expansion, + is_macro_export: false, }); let _ = self.try_define(directive.parent, target, TypeNS, binding); return None; @@ -800,7 +805,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if all_ns_err { let mut all_ns_failed = true; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { - match this.resolve_ident_in_module(module, ident, ns, false, true, span) { + match this.resolve_ident_in_module(module, ident, ns, true, span) { Ok(_) => all_ns_failed = false, _ => {} } @@ -969,25 +974,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { *module.globs.borrow_mut() = Vec::new(); let mut reexports = Vec::new(); - let mut exported_macro_names = FxHashMap(); - if module as *const _ == self.graph_root as *const _ { - let macro_exports = mem::replace(&mut self.macro_exports, Vec::new()); - for export in macro_exports.into_iter().rev() { - if let Some(later_span) = exported_macro_names.insert(export.ident.modern(), - export.span) { - self.session.buffer_lint_with_diagnostic( - DUPLICATE_MACRO_EXPORTS, - CRATE_NODE_ID, - later_span, - &format!("a macro named `{}` has already been exported", export.ident), - BuiltinLintDiagnostics::DuplicatedMacroExports( - export.ident, export.span, later_span)); - } else { - reexports.push(export); - } - } - } - for (&(ident, ns), resolution) in module.resolutions.borrow().iter() { let resolution = &mut *resolution.borrow_mut(); let binding = match resolution.binding { @@ -1001,16 +987,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if !def.def_id().is_local() { self.cstore.export_macros_untracked(def.def_id().krate); } - if let Def::Macro(..) = def { - if let Some(&span) = exported_macro_names.get(&ident.modern()) { - let msg = - format!("a macro named `{}` has already been exported", ident); - self.session.struct_span_err(span, &msg) - .span_label(span, format!("`{}` already exported", ident)) - .span_note(binding.span, "previous macro export here") - .emit(); - } - } reexports.push(Export { ident: ident.modern(), def: def, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f71d62d5a04e1..0faaba3f16103 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1220,15 +1220,13 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option { .resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false); if let Ok(def) = res { if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(def) { - Some(def) - } else { - None + return Some(def); } - } else if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) { - Some(*def) - } else { - None } + if let Some(def) = resolver.all_macros.get(&Symbol::intern(path_str)) { + return Some(*def); + } + None } #[derive(Debug)] diff --git a/src/test/run-pass/auxiliary/issue_38715.rs b/src/test/run-pass/auxiliary/issue_38715.rs deleted file mode 100644 index cf4fee0e515c9..0000000000000 --- a/src/test/run-pass/auxiliary/issue_38715.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![allow(duplicate_macro_exports)] - -#[macro_export] -macro_rules! foo { ($i:ident) => {} } - -#[macro_export] -macro_rules! foo { () => {} } diff --git a/src/test/ui/duplicate-check-macro-exports.rs b/src/test/ui/duplicate-check-macro-exports.rs index 5db46075d1c8b..42b2b1d650f76 100644 --- a/src/test/ui/duplicate-check-macro-exports.rs +++ b/src/test/ui/duplicate-check-macro-exports.rs @@ -11,6 +11,6 @@ pub use std::panic; #[macro_export] -macro_rules! panic { () => {} } //~ ERROR a macro named `panic` has already been exported +macro_rules! panic { () => {} } //~ ERROR the name `panic` is defined multiple times fn main() {} diff --git a/src/test/ui/duplicate-check-macro-exports.stderr b/src/test/ui/duplicate-check-macro-exports.stderr index 196a2bd8511f8..e2119efbd3db5 100644 --- a/src/test/ui/duplicate-check-macro-exports.stderr +++ b/src/test/ui/duplicate-check-macro-exports.stderr @@ -1,14 +1,18 @@ -error: a macro named `panic` has already been exported +error[E0255]: the name `panic` is defined multiple times --> $DIR/duplicate-check-macro-exports.rs:14:1 | -LL | macro_rules! panic { () => {} } //~ ERROR a macro named `panic` has already been exported - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `panic` already exported +LL | pub use std::panic; + | ---------- previous import of the macro `panic` here +... +LL | macro_rules! panic { () => {} } //~ ERROR the name `panic` is defined multiple times + | ^^^^^^^^^^^^^^^^^^ `panic` redefined here | -note: previous macro export here - --> $DIR/duplicate-check-macro-exports.rs:11:9 + = note: `panic` must be defined only once in the macro namespace of this module +help: You can use `as` to change the binding name of the import | -LL | pub use std::panic; - | ^^^^^^^^^^ +LL | pub use std::panic as other_panic; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0255`. diff --git a/src/test/ui/error-codes/E0659.stderr b/src/test/ui/error-codes/E0659.stderr index 06176085b3813..e99cd243e4019 100644 --- a/src/test/ui/error-codes/E0659.stderr +++ b/src/test/ui/error-codes/E0659.stderr @@ -1,4 +1,4 @@ -error[E0659]: `foo` is ambiguous +error[E0659]: `foo` is ambiguous RecordUse --> $DIR/E0659.rs:25:5 | LL | collider::foo(); //~ ERROR E0659 diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr index 452e3e1e2008f..d107d49fdb421 100644 --- a/src/test/ui/imports/duplicate.stderr +++ b/src/test/ui/imports/duplicate.stderr @@ -12,7 +12,7 @@ help: You can use `as` to change the binding name of the import LL | use a::foo as other_foo; //~ ERROR the name `foo` is defined multiple times | ^^^^^^^^^^^^^^^^^^^ -error[E0659]: `foo` is ambiguous +error[E0659]: `foo` is ambiguous RecordUse --> $DIR/duplicate.rs:56:9 | LL | use self::foo::bar; //~ ERROR `foo` is ambiguous @@ -30,7 +30,7 @@ LL | use self::m2::*; | ^^^^^^^^^^^ = note: consider adding an explicit import of `foo` to disambiguate -error[E0659]: `foo` is ambiguous +error[E0659]: `foo` is ambiguous RecordUse --> $DIR/duplicate.rs:45:5 | LL | f::foo(); //~ ERROR `foo` is ambiguous @@ -48,7 +48,7 @@ LL | pub use b::*; | ^^^^ = note: consider adding an explicit import of `foo` to disambiguate -error[E0659]: `foo` is ambiguous +error[E0659]: `foo` is ambiguous RecordUse --> $DIR/duplicate.rs:46:5 | LL | g::foo(); //~ ERROR `foo` is ambiguous @@ -66,7 +66,7 @@ LL | pub use f::*; | ^^^^ = note: consider adding an explicit import of `foo` to disambiguate -error[E0659]: `foo` is ambiguous +error[E0659]: `foo` is ambiguous RecordUse --> $DIR/duplicate.rs:59:9 | LL | foo::bar(); //~ ERROR `foo` is ambiguous diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs new file mode 100644 index 0000000000000..40b95328273aa --- /dev/null +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs @@ -0,0 +1,56 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(decl_macro)] + +macro_rules! define_exported { () => { + #[macro_export] + macro_rules! exported { + () => () + } +}} +macro_rules! define_panic { () => { + #[macro_export] + macro_rules! panic { + () => () + } +}} +macro_rules! define_include { () => { + #[macro_export] + macro_rules! include { + () => () + } +}} + +use inner1::*; + +mod inner1 { + pub macro exported() {} +} + +exported!(); //~ ERROR `exported` is ambiguous RecordUse + +mod inner2 { + define_exported!(); +} + +fn main() { + panic!(); //~ ERROR `panic` is ambiguous ResolveLexical +} + +mod inner3 { + define_panic!(); +} + +mod inner4 { + define_include!(); +} + +include!(); //~ ERROR `include` is ambiguous ResolveLexical diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr new file mode 100644 index 0000000000000..f1fc631f24189 --- /dev/null +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -0,0 +1,84 @@ +error[E0659]: `exported` is ambiguous RecordUse + --> $DIR/local-modularized-tricky-fail-1.rs:38:1 + | +LL | exported!(); //~ ERROR `exported` is ambiguous RecordUse + | ^^^^^^^^ + | +note: `exported` could refer to the name defined here + --> $DIR/local-modularized-tricky-fail-1.rs:15:5 + | +LL | / macro_rules! exported { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_exported!(); + | ------------------- in this macro invocation +note: `exported` could also refer to the name imported here + --> $DIR/local-modularized-tricky-fail-1.rs:32:5 + | +LL | use inner1::*; + | ^^^^^^^^^ + = note: macro-expanded macros do not shadow + +error[E0659]: `include` is ambiguous ResolveLexical + --> $DIR/local-modularized-tricky-fail-1.rs:56:1 + | +LL | include!(); //~ ERROR `include` is ambiguous ResolveLexical + | ^^^^^^^ + | +note: `include` could refer to the name defined here + --> $DIR/local-modularized-tricky-fail-1.rs:27:5 + | +LL | / macro_rules! include { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_include!(); + | ------------------ in this macro invocation + = note: `include` is also a builtin macro + = note: macro-expanded macros do not shadow + +error[E0659]: `panic` is ambiguous ResolveLexical + --> $DIR/local-modularized-tricky-fail-1.rs:45:5 + | +LL | panic!(); //~ ERROR `panic` is ambiguous ResolveLexical + | ^^^^^ + | +note: `panic` could refer to the name defined here + --> $DIR/local-modularized-tricky-fail-1.rs:21:5 + | +LL | / macro_rules! panic { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_panic!(); + | ---------------- in this macro invocation + = note: `panic` is also a builtin macro + = note: macro-expanded macros do not shadow + +error[E0659]: `panic` is ambiguous ResolveLexical + --> $DIR/local-modularized-tricky-fail-1.rs:45:5 + | +LL | panic!(); //~ ERROR `panic` is ambiguous ResolveLexical + | ^^^^^^^^^ + | +note: `panic` could refer to the name defined here + --> $DIR/local-modularized-tricky-fail-1.rs:21:5 + | +LL | / macro_rules! panic { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_panic!(); + | ---------------- in this macro invocation + = note: `panic` is also a builtin macro + = note: macro-expanded macros do not shadow + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.rs b/src/test/ui/imports/local-modularized-tricky-fail-2.rs new file mode 100644 index 0000000000000..afdebc4533ff6 --- /dev/null +++ b/src/test/ui/imports/local-modularized-tricky-fail-2.rs @@ -0,0 +1,58 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// `#[macro_export] macro_rules` that doen't originate from macro expansions can be placed +// into the root module soon enough to act as usual items and shadow globs and preludes. + +#![feature(decl_macro)] + +// `macro_export` shadows globs +use inner1::*; + +mod inner1 { + pub macro exported() {} +} + +exported!(); + +mod deep { + fn deep() { + type Deeper = [u8; { + #[macro_export] + macro_rules! exported { + () => ( struct Б; ) //~ ERROR non-ascii idents are not fully supported + } + + 0 + }]; + } +} + +// `macro_export` shadows std prelude +fn main() { + panic!(); +} + +mod inner3 { + #[macro_export] + macro_rules! panic { + () => ( struct Г; ) //~ ERROR non-ascii idents are not fully supported + } +} + +// `macro_export` shadows builtin macros +include!(); + +mod inner4 { + #[macro_export] + macro_rules! include { + () => ( struct Д; ) //~ ERROR non-ascii idents are not fully supported + } +} diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr new file mode 100644 index 0000000000000..5681dd5962850 --- /dev/null +++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr @@ -0,0 +1,36 @@ +error[E0658]: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/local-modularized-tricky-fail-2.rs:30:32 + | +LL | exported!(); + | ------------ in this macro invocation +... +LL | () => ( struct Б; ) //~ ERROR non-ascii idents are not fully supported + | ^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error[E0658]: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/local-modularized-tricky-fail-2.rs:46:24 + | +LL | panic!(); + | --------- in this macro invocation +... +LL | () => ( struct Г; ) //~ ERROR non-ascii idents are not fully supported + | ^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error[E0658]: non-ascii idents are not fully supported. (see issue #28979) + --> $DIR/local-modularized-tricky-fail-2.rs:56:24 + | +LL | include!(); + | ----------- in this macro invocation +... +LL | () => ( struct Д; ) //~ ERROR non-ascii idents are not fully supported + | ^ + | + = help: add #![feature(non_ascii_idents)] to the crate attributes to enable + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/run-pass/issue-38715.rs b/src/test/ui/imports/local-modularized-tricky-pass.rs similarity index 58% rename from src/test/run-pass/issue-38715.rs rename to src/test/ui/imports/local-modularized-tricky-pass.rs index 054785e62b8ea..9392473eace66 100644 --- a/src/test/run-pass/issue-38715.rs +++ b/src/test/ui/imports/local-modularized-tricky-pass.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,13 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue_38715.rs +// compile-pass -// Test that `#[macro_export] macro_rules!` shadow earlier `#[macro_export] macro_rules!` +macro_rules! define_exported { () => { + #[macro_export] + macro_rules! exported { + () => () + } +}} -#[macro_use] -extern crate issue_38715; +mod inner1 { + use super::*; + exported!(); +} -fn main() { - foo!(); +mod inner2 { + define_exported!(); } + +fn main() {} diff --git a/src/test/ui/imports/local-modularized.rs b/src/test/ui/imports/local-modularized.rs new file mode 100644 index 0000000000000..260a406ef75f9 --- /dev/null +++ b/src/test/ui/imports/local-modularized.rs @@ -0,0 +1,45 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#[macro_export(local_inner_macros)] +macro_rules! dollar_crate_exported { + (1) => { $crate::exported!(); }; + (2) => { exported!(); }; +} + +// Before `exported` is defined +exported!(); + +mod inner { + + ::exported!(); + crate::exported!(); + dollar_crate_exported!(1); + dollar_crate_exported!(2); + + mod inner_inner { + #[macro_export] + macro_rules! exported { + () => () + } + } + + // After `exported` is defined + ::exported!(); + crate::exported!(); + dollar_crate_exported!(1); + dollar_crate_exported!(2); +} + +exported!(); + +fn main() {} diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr index 08f45e1a57530..ade415544f0a9 100644 --- a/src/test/ui/imports/macro-paths.stderr +++ b/src/test/ui/imports/macro-paths.stderr @@ -1,4 +1,4 @@ -error[E0659]: `bar` is ambiguous +error[E0659]: `bar` is ambiguous ResolveInModule --> $DIR/macro-paths.rs:23:5 | LL | bar::m! { //~ ERROR ambiguous @@ -16,7 +16,7 @@ LL | use foo::*; | ^^^^^^ = note: macro-expanded items do not shadow when used in a macro invocation path -error[E0659]: `baz` is ambiguous +error[E0659]: `baz` is ambiguous ResolveLexical --> $DIR/macro-paths.rs:33:5 | LL | baz::m! { //~ ERROR ambiguous diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr index 01d1f4fdfad03..0e13e5cf11d08 100644 --- a/src/test/ui/imports/macros.stderr +++ b/src/test/ui/imports/macros.stderr @@ -15,7 +15,7 @@ note: `m` could also refer to the macro imported here LL | use two_macros::m; | ^^^^^^^^^^^^^ -error[E0659]: `m` is ambiguous +error[E0659]: `m` is ambiguous RecordUse --> $DIR/macros.rs:26:5 | LL | m! { //~ ERROR ambiguous @@ -33,7 +33,7 @@ LL | use two_macros::*; | ^^^^^^^^^^^^^ = note: macro-expanded macro imports do not shadow -error[E0659]: `m` is ambiguous +error[E0659]: `m` is ambiguous ResolveLexical --> $DIR/macros.rs:39:9 | LL | m! { //~ ERROR ambiguous diff --git a/src/test/ui/imports/rfc-1560-warning-cycle.stderr b/src/test/ui/imports/rfc-1560-warning-cycle.stderr index 5a01680fc1921..aa41049406ccf 100644 --- a/src/test/ui/imports/rfc-1560-warning-cycle.stderr +++ b/src/test/ui/imports/rfc-1560-warning-cycle.stderr @@ -1,4 +1,4 @@ -error[E0659]: `Foo` is ambiguous +error[E0659]: `Foo` is ambiguous RecordUse --> $DIR/rfc-1560-warning-cycle.rs:19:17 | LL | fn f(_: Foo) {} //~ ERROR `Foo` is ambiguous diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index 693b7aadeca4e..43cce402566fe 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -9,7 +9,7 @@ LL | m!(); | = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560) -error[E0659]: `panic` is ambiguous +error[E0659]: `panic` is ambiguous ResolveLexical --> $DIR/shadow_builtin_macros.rs:25:14 | LL | fn f() { panic!(); } //~ ERROR ambiguous @@ -23,7 +23,7 @@ LL | use foo::*; = note: `panic` is also a builtin macro = note: consider adding an explicit import of `panic` to disambiguate -error[E0659]: `panic` is ambiguous +error[E0659]: `panic` is ambiguous ResolveLexical --> $DIR/shadow_builtin_macros.rs:30:14 | LL | fn f() { panic!(); } //~ ERROR ambiguous @@ -37,7 +37,7 @@ LL | ::two_macros::m!(use foo::panic;); = note: `panic` is also a builtin macro = note: macro-expanded macro imports do not shadow -error[E0659]: `n` is ambiguous +error[E0659]: `n` is ambiguous ResolveLexical --> $DIR/shadow_builtin_macros.rs:59:5 | LL | n!(); //~ ERROR ambiguous diff --git a/src/test/ui/issue-38715.rs b/src/test/ui/issue-38715.rs index 552653c21bad6..bc09f231f6b62 100644 --- a/src/test/ui/issue-38715.rs +++ b/src/test/ui/issue-38715.rs @@ -12,5 +12,4 @@ macro_rules! foo { ($i:ident) => {} } #[macro_export] -macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported - //~| WARN this was previously accepted +macro_rules! foo { () => {} } //~ ERROR the name `foo` is defined multiple times diff --git a/src/test/ui/issue-38715.stderr b/src/test/ui/issue-38715.stderr index a0dbcbd18c673..7204a1cafea1c 100644 --- a/src/test/ui/issue-38715.stderr +++ b/src/test/ui/issue-38715.stderr @@ -1,17 +1,13 @@ -error: a macro named `foo` has already been exported +error[E0428]: the name `foo` is defined multiple times --> $DIR/issue-38715.rs:15:1 | -LL | macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` already exported - | - = note: #[deny(duplicate_macro_exports)] on by default - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! - = note: for more information, see issue #35896 -note: previous macro export is now shadowed - --> $DIR/issue-38715.rs:12:1 - | LL | macro_rules! foo { ($i:ident) => {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------------- previous definition of the macro `foo` here +... +LL | macro_rules! foo { () => {} } //~ ERROR the name `foo` is defined multiple times + | ^^^^^^^^^^^^^^^^ `foo` redefined here + | + = note: `foo` must be defined only once in the macro namespace of this module error[E0601]: `main` function not found in crate `issue_38715` | @@ -19,4 +15,5 @@ error[E0601]: `main` function not found in crate `issue_38715` error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0601`. +Some errors occurred: E0428, E0601. +For more information about an error, try `rustc --explain E0428`. diff --git a/src/test/ui/macros/macro_undefined.rs b/src/test/ui/macros/macro_undefined.rs index c0acbc979ad1f..4a812739a6b26 100644 --- a/src/test/ui/macros/macro_undefined.rs +++ b/src/test/ui/macros/macro_undefined.rs @@ -19,5 +19,5 @@ mod m { fn main() { k!(); //~ ERROR cannot find - kl!(); //~ ERROR cannot find + kl!(); } diff --git a/src/test/ui/macros/macro_undefined.stderr b/src/test/ui/macros/macro_undefined.stderr index 8d44df8af0cbd..87b039f483485 100644 --- a/src/test/ui/macros/macro_undefined.stderr +++ b/src/test/ui/macros/macro_undefined.stderr @@ -1,16 +1,8 @@ -error: cannot find macro `kl!` in this scope - --> $DIR/macro_undefined.rs:22:5 - | -LL | kl!(); //~ ERROR cannot find - | ^^ - | - = help: have you added the `#[macro_use]` on the module/import? - error: cannot find macro `k!` in this scope --> $DIR/macro_undefined.rs:21:5 | LL | k!(); //~ ERROR cannot find | ^ help: you could try the macro: `kl` -error: aborting due to 2 previous errors +error: aborting due to previous error