Skip to content

Commit 11c283c

Browse files
committed
Prohibit duplicate macro_exports
1 parent 20af72b commit 11c283c

File tree

8 files changed

+86
-5
lines changed

8 files changed

+86
-5
lines changed

src/librustc/lint/builtin.rs

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use errors::{Applicability, DiagnosticBuilder};
1818
use lint::{LintPass, LateLintPass, LintArray};
1919
use session::Session;
20+
use syntax::ast;
2021
use syntax::codemap::Span;
2122

2223
declare_lint! {
@@ -285,6 +286,12 @@ declare_lint! {
285286
"warns about duplicate associated type bindings in generics"
286287
}
287288

289+
declare_lint! {
290+
pub DUPLICATE_MACRO_EXPORTS,
291+
Deny,
292+
"detects duplicate macro exports"
293+
}
294+
288295
/// Does nothing as a lint pass, but registers some `Lint`s
289296
/// which are used by other parts of the compiler.
290297
#[derive(Copy, Clone)]
@@ -337,6 +344,7 @@ impl LintPass for HardwiredLints {
337344
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
338345
UNSTABLE_NAME_COLLISIONS,
339346
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
347+
DUPLICATE_MACRO_EXPORTS,
340348
)
341349
}
342350
}
@@ -348,6 +356,7 @@ pub enum BuiltinLintDiagnostics {
348356
Normal,
349357
BareTraitObject(Span, /* is_global */ bool),
350358
AbsPathWithModule(Span),
359+
DuplicatedMacroExports(ast::Ident, Span, Span),
351360
}
352361

353362
impl BuiltinLintDiagnostics {
@@ -380,6 +389,10 @@ impl BuiltinLintDiagnostics {
380389
};
381390
db.span_suggestion_with_applicability(span, "use `crate`", sugg, app);
382391
}
392+
BuiltinLintDiagnostics::DuplicatedMacroExports(ident, earlier_span, later_span) => {
393+
db.span_label(later_span, format!("`{}` already exported", ident));
394+
db.span_note(earlier_span, "previous macro export is now shadowed");
395+
}
383396
}
384397
}
385398
}

src/librustc_lint/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
212212
reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
213213
edition: None,
214214
},
215+
FutureIncompatibleInfo {
216+
id: LintId::of(DUPLICATE_MACRO_EXPORTS),
217+
reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
218+
edition: Some(Edition::Edition2018),
219+
},
215220
FutureIncompatibleInfo {
216221
id: LintId::of(SAFE_EXTERN_STATICS),
217222
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",

src/librustc_resolve/resolve_imports.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ use {names_to_string, module_to_string};
1818
use {resolve_error, ResolutionError};
1919

2020
use rustc::ty;
21-
use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE;
21+
use rustc::lint::builtin::BuiltinLintDiagnostics;
22+
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
2223
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
2324
use rustc::hir::def::*;
2425
use rustc::session::DiagnosticMessageId;
2526
use rustc::util::nodemap::{FxHashMap, FxHashSet};
2627

27-
use syntax::ast::{Ident, Name, NodeId};
28+
use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID};
2829
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
2930
use syntax::ext::hygiene::Mark;
3031
use syntax::symbol::keywords;
@@ -974,7 +975,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
974975
if module as *const _ == self.graph_root as *const _ {
975976
let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
976977
for export in macro_exports.into_iter().rev() {
977-
if exported_macro_names.insert(export.ident.modern(), export.span).is_none() {
978+
if let Some(later_span) = exported_macro_names.insert(export.ident.modern(),
979+
export.span) {
980+
self.session.buffer_lint_with_diagnostic(
981+
DUPLICATE_MACRO_EXPORTS,
982+
CRATE_NODE_ID,
983+
later_span,
984+
&format!("a macro named `{}` has already been exported", export.ident),
985+
BuiltinLintDiagnostics::DuplicatedMacroExports(
986+
export.ident, export.span, later_span));
987+
} else {
978988
reexports.push(export);
979989
}
980990
}

src/test/run-pass/auxiliary/issue_38715.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#![allow(duplicate_macro_exports)]
12+
1113
#[macro_export]
1214
macro_rules! foo { ($i:ident) => {} }
1315

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! macro_one { ($($t:tt)*) => ($($t)*) }
12+
13+
macro_rules! macro_two { ($($t:tt)*) => ($($t)*) }

src/test/run-pass/mod_dir_path.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ pub fn main() {
2020

2121
#[path = "auxiliary"]
2222
mod foo {
23-
mod two_macros;
23+
mod two_macros_2;
2424
}
2525

2626
#[path = "auxiliary"]
2727
mod bar {
28-
macro_rules! m { () => { mod two_macros; } }
28+
macro_rules! m { () => { mod two_macros_2; } }
2929
m!();
3030
}
3131
}

src/test/ui/issue-38715.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[macro_export]
12+
macro_rules! foo { ($i:ident) => {} }
13+
14+
#[macro_export]
15+
macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
16+
//~| WARN this was previously accepted

src/test/ui/issue-38715.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: a macro named `foo` has already been exported
2+
--> $DIR/issue-38715.rs:15:1
3+
|
4+
LL | macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` already exported
6+
|
7+
= note: #[deny(duplicate_macro_exports)] on by default
8+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
9+
= note: for more information, see issue #35896 <https://github.com/rust-lang/rust/issues/35896>
10+
note: previous macro export is now shadowed
11+
--> $DIR/issue-38715.rs:12:1
12+
|
13+
LL | macro_rules! foo { ($i:ident) => {} }
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
16+
error[E0601]: `main` function not found in crate `issue_38715`
17+
|
18+
= note: consider adding a `main` function to `$DIR/issue-38715.rs`
19+
20+
error: aborting due to 2 previous errors
21+
22+
For more information about this error, try `rustc --explain E0601`.

0 commit comments

Comments
 (0)