diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f1be821d526e1..5b633e3d46223 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1200,7 +1200,7 @@ pub struct Resolver<'a> { pub found_unresolved_macro: bool, // List of crate local macros that we need to warn about as being unused. - // Right now this only includes macro_rules! macros. + // Right now this only includes macro_rules! macros, and macros 2.0. unused_macros: FxHashSet, // Maps the `Mark` of an expansion to its containing module or block. diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 9a37df7623279..a950a9a23e47c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -316,6 +316,7 @@ impl<'a> base::Resolver for Resolver<'a> { for did in self.unused_macros.iter() { let id_span = match *self.macro_map[did] { SyntaxExtension::NormalTT(_, isp, _) => isp, + SyntaxExtension::DeclMacro(.., osp) => osp, _ => None, }; if let Some((id, span)) = id_span { @@ -735,6 +736,9 @@ impl<'a> Resolver<'a> { let module = self.current_module; let def = Def::Macro(def_id, MacroKind::Bang); let vis = self.resolve_visibility(&item.vis); + if vis != ty::Visibility::Public { + self.unused_macros.insert(def_id); + } self.define(module, ident, MacroNS, (def, vis, item.span, expansion)); } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 71dc81c375923..8089fad5f36d8 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -552,7 +552,9 @@ pub enum SyntaxExtension { BuiltinDerive(BuiltinDeriveFn), /// A declarative macro, e.g. `macro m() {}`. - DeclMacro(Box, Option /* definition site span */), + /// + /// The second element is the definition site span. + DeclMacro(Box, Option<(ast::NodeId, Span)>), } impl SyntaxExtension { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index be077b481113f..c91c77719e699 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -472,8 +472,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let marked_tts = noop_fold_tts(mac.node.stream(), &mut Marker(mark)); let opt_expanded = match *ext { - SyntaxExtension::DeclMacro(ref expand, def_site_span) => { - if let Err(msg) = validate_and_set_expn_info(def_site_span, false) { + SyntaxExtension::DeclMacro(ref expand, def_span) => { + if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s), + false) { self.cx.span_err(path.span, &msg); return kind.dummy(span); } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 15042e529e51a..0472a94e0ced6 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -266,7 +266,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable"); NormalTT(exp, Some((def.id, def.span)), allow_internal_unstable) } else { - SyntaxExtension::DeclMacro(exp, Some(def.span)) + SyntaxExtension::DeclMacro(exp, Some((def.id, def.span))) } } diff --git a/src/test/compile-fail/feature-gate-decl_macro.rs b/src/test/compile-fail/feature-gate-decl_macro.rs index af7d5fec07199..c5c83977c77fd 100644 --- a/src/test/compile-fail/feature-gate-decl_macro.rs +++ b/src/test/compile-fail/feature-gate-decl_macro.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(unused_macros)] + macro m() {} //~ ERROR `macro` is experimental (see issue #39412) //~| HELP add #![feature(decl_macro)] to the crate attributes to enable diff --git a/src/test/compile-fail/unused-macro-rules.rs b/src/test/compile-fail/unused-macro-rules.rs new file mode 100644 index 0000000000000..5e401c09bda59 --- /dev/null +++ b/src/test/compile-fail/unused-macro-rules.rs @@ -0,0 +1,39 @@ +// Copyright 2017 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. + +#![deny(unused_macros)] + +// Most simple case +macro_rules! unused { //~ ERROR: unused macro definition + () => {}; +} + +// Test macros created by macros +macro_rules! create_macro { + () => { + macro_rules! m { //~ ERROR: unused macro definition + () => {}; + } + }; +} +create_macro!(); + +#[allow(unused_macros)] +mod bar { + // Test that putting the #[deny] close to the macro's definition + // works. + + #[deny(unused_macros)] + macro_rules! unused { //~ ERROR: unused macro definition + () => {}; + } +} + +fn main() {} diff --git a/src/test/compile-fail/unused-macro.rs b/src/test/compile-fail/unused-macro.rs index 5e401c09bda59..9e32f01724d02 100644 --- a/src/test/compile-fail/unused-macro.rs +++ b/src/test/compile-fail/unused-macro.rs @@ -8,31 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(decl_macro)] #![deny(unused_macros)] // Most simple case -macro_rules! unused { //~ ERROR: unused macro definition - () => {}; +macro unused { //~ ERROR: unused macro definition + () => {} } -// Test macros created by macros -macro_rules! create_macro { - () => { - macro_rules! m { //~ ERROR: unused macro definition - () => {}; - } - }; -} -create_macro!(); - #[allow(unused_macros)] mod bar { // Test that putting the #[deny] close to the macro's definition // works. #[deny(unused_macros)] - macro_rules! unused { //~ ERROR: unused macro definition - () => {}; + macro unused { //~ ERROR: unused macro definition + () => {} + } +} + +mod boo { + pub(crate) macro unused { //~ ERROR: unused macro definition + () => {} } }