From 11c283cdfc536c2d0c984bea47c7ab246d4ed5d3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 21 Apr 2018 17:18:38 +0300 Subject: [PATCH] Prohibit duplicate `macro_export`s --- src/librustc/lint/builtin.rs | 13 ++++++++++++ src/librustc_lint/lib.rs | 5 +++++ src/librustc_resolve/resolve_imports.rs | 16 ++++++++++++--- src/test/run-pass/auxiliary/issue_38715.rs | 2 ++ src/test/run-pass/auxiliary/two_macros_2.rs | 13 ++++++++++++ src/test/run-pass/mod_dir_path.rs | 4 ++-- src/test/ui/issue-38715.rs | 16 +++++++++++++++ src/test/ui/issue-38715.stderr | 22 +++++++++++++++++++++ 8 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 src/test/run-pass/auxiliary/two_macros_2.rs create mode 100644 src/test/ui/issue-38715.rs create mode 100644 src/test/ui/issue-38715.stderr diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index de583e81ca831..d0cf30b6e069d 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -17,6 +17,7 @@ use errors::{Applicability, DiagnosticBuilder}; use lint::{LintPass, LateLintPass, LintArray}; use session::Session; +use syntax::ast; use syntax::codemap::Span; declare_lint! { @@ -285,6 +286,12 @@ declare_lint! { "warns about duplicate associated type bindings in generics" } +declare_lint! { + pub DUPLICATE_MACRO_EXPORTS, + Deny, + "detects duplicate macro exports" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -337,6 +344,7 @@ impl LintPass for HardwiredLints { ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, UNSTABLE_NAME_COLLISIONS, DUPLICATE_ASSOCIATED_TYPE_BINDINGS, + DUPLICATE_MACRO_EXPORTS, ) } } @@ -348,6 +356,7 @@ pub enum BuiltinLintDiagnostics { Normal, BareTraitObject(Span, /* is_global */ bool), AbsPathWithModule(Span), + DuplicatedMacroExports(ast::Ident, Span, Span), } impl BuiltinLintDiagnostics { @@ -380,6 +389,10 @@ impl BuiltinLintDiagnostics { }; db.span_suggestion_with_applicability(span, "use `crate`", sugg, app); } + BuiltinLintDiagnostics::DuplicatedMacroExports(ident, earlier_span, later_span) => { + db.span_label(later_span, format!("`{}` already exported", ident)); + db.span_note(earlier_span, "previous macro export is now shadowed"); + } } } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index c5994d0536ee0..6905b7beeef47 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -212,6 +212,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { reference: "issue #35203 ", edition: None, }, + FutureIncompatibleInfo { + id: LintId::of(DUPLICATE_MACRO_EXPORTS), + reference: "issue #35896 ", + edition: Some(Edition::Edition2018), + }, FutureIncompatibleInfo { id: LintId::of(SAFE_EXTERN_STATICS), reference: "issue #36247 ", diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 34f84597adfc5..df96f5982cbfc 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -18,13 +18,14 @@ use {names_to_string, module_to_string}; use {resolve_error, ResolutionError}; use rustc::ty; -use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE; +use rustc::lint::builtin::BuiltinLintDiagnostics; +use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, 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 syntax::ast::{Ident, Name, NodeId}; +use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; use syntax::symbol::keywords; @@ -974,7 +975,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { 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 exported_macro_names.insert(export.ident.modern(), export.span).is_none() { + 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); } } diff --git a/src/test/run-pass/auxiliary/issue_38715.rs b/src/test/run-pass/auxiliary/issue_38715.rs index cad3996eadbfb..cf4fee0e515c9 100644 --- a/src/test/run-pass/auxiliary/issue_38715.rs +++ b/src/test/run-pass/auxiliary/issue_38715.rs @@ -8,6 +8,8 @@ // 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) => {} } diff --git a/src/test/run-pass/auxiliary/two_macros_2.rs b/src/test/run-pass/auxiliary/two_macros_2.rs new file mode 100644 index 0000000000000..b16cd3a421095 --- /dev/null +++ b/src/test/run-pass/auxiliary/two_macros_2.rs @@ -0,0 +1,13 @@ +// Copyright 2015 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_rules! macro_one { ($($t:tt)*) => ($($t)*) } + +macro_rules! macro_two { ($($t:tt)*) => ($($t)*) } diff --git a/src/test/run-pass/mod_dir_path.rs b/src/test/run-pass/mod_dir_path.rs index e2f33963c4bad..fc91ea870d51a 100644 --- a/src/test/run-pass/mod_dir_path.rs +++ b/src/test/run-pass/mod_dir_path.rs @@ -20,12 +20,12 @@ pub fn main() { #[path = "auxiliary"] mod foo { - mod two_macros; + mod two_macros_2; } #[path = "auxiliary"] mod bar { - macro_rules! m { () => { mod two_macros; } } + macro_rules! m { () => { mod two_macros_2; } } m!(); } } diff --git a/src/test/ui/issue-38715.rs b/src/test/ui/issue-38715.rs new file mode 100644 index 0000000000000..552653c21bad6 --- /dev/null +++ b/src/test/ui/issue-38715.rs @@ -0,0 +1,16 @@ +// 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. + +#[macro_export] +macro_rules! foo { ($i:ident) => {} } + +#[macro_export] +macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported + //~| WARN this was previously accepted diff --git a/src/test/ui/issue-38715.stderr b/src/test/ui/issue-38715.stderr new file mode 100644 index 0000000000000..a0dbcbd18c673 --- /dev/null +++ b/src/test/ui/issue-38715.stderr @@ -0,0 +1,22 @@ +error: a macro named `foo` has already been exported + --> $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) => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0601]: `main` function not found in crate `issue_38715` + | + = note: consider adding a `main` function to `$DIR/issue-38715.rs` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0601`.