Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Prohibit duplicate macro_exports
  • Loading branch information
petrochenkov committed May 30, 2018
1 parent 20af72b commit 11c283c
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 5 deletions.
13 changes: 13 additions & 0 deletions src/librustc/lint/builtin.rs
Expand Up @@ -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! {
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -337,6 +344,7 @@ impl LintPass for HardwiredLints {
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
UNSTABLE_NAME_COLLISIONS,
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
DUPLICATE_MACRO_EXPORTS,
)
}
}
Expand All @@ -348,6 +356,7 @@ pub enum BuiltinLintDiagnostics {
Normal,
BareTraitObject(Span, /* is_global */ bool),
AbsPathWithModule(Span),
DuplicatedMacroExports(ast::Ident, Span, Span),
}

impl BuiltinLintDiagnostics {
Expand Down Expand Up @@ -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");
}
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_lint/lib.rs
Expand Up @@ -212,6 +212,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
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>",
Expand Down
16 changes: 13 additions & 3 deletions src/librustc_resolve/resolve_imports.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/run-pass/auxiliary/issue_38715.rs
Expand Up @@ -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) => {} }

Expand Down
13 changes: 13 additions & 0 deletions 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 <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)*) }
4 changes: 2 additions & 2 deletions src/test/run-pass/mod_dir_path.rs
Expand Up @@ -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!();
}
}
16 changes: 16 additions & 0 deletions 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 <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
22 changes: 22 additions & 0 deletions 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 <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`.

0 comments on commit 11c283c

Please sign in to comment.