use errors::{Applicability, DiagnosticBuilder};
use lint::{LintPass, LateLintPass, LintArray};
use session::Session;
+use syntax::ast;
use syntax::codemap::Span;
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)]
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
UNSTABLE_NAME_COLLISIONS,
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
+ DUPLICATE_MACRO_EXPORTS,
)
}
}
Normal,
BareTraitObject(Span, /* is_global */ bool),
AbsPathWithModule(Span),
+ DuplicatedMacroExports(ast::Ident, Span, Span),
}
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");
+ }
}
}
}
reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
edition: None,
},
+ FutureIncompatibleInfo {
+ id: LintId::of(DUPLICATE_MACRO_EXPORTS),
+ reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
+ edition: Some(Edition::Edition2018),
+ },
FutureIncompatibleInfo {
id: LintId::of(SAFE_EXTERN_STATICS),
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
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;
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);
}
}
// 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) => {} }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! macro_one { ($($t:tt)*) => ($($t)*) }
+
+macro_rules! macro_two { ($($t:tt)*) => ($($t)*) }
#[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!();
}
}
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_export]
+macro_rules! foo { ($i:ident) => {} }
+
+#[macro_export]
+macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
+ //~| WARN this was previously accepted
--- /dev/null
+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 <https://github.com/rust-lang/rust/issues/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`.