diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index d83bd8b922395..171bfd74a816b 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -552,7 +552,10 @@ impl<'a> PluginMetadata<'a> { id: ast::DUMMY_NODE_ID, span: span, imported_from: imported_from, - export: false, // overridden in plugin/load.rs + // overridden in plugin/load.rs + export: false, + use_locally: false, + body: body, }); true diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 93c97f6caa66a..3a9083828fc70 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -87,8 +87,8 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } // Parse the attributes relating to macro / plugin loading. - let mut load_macros = false; let mut load_registrar = false; + let mut macro_selection = Some(HashSet::new()); // None => load all let mut reexport = HashSet::new(); for attr in vi.attrs.iter() { let mut used = true; @@ -98,7 +98,22 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { #[macro_use], #[plugin], and/or #[no_link]"); } "plugin" => load_registrar = true, - "macro_use" => load_macros = true, + "macro_use" => { + let names = attr.meta_item_list(); + if names.is_none() { + // no names => load all + macro_selection = None; + } + if let (Some(sel), Some(names)) = (macro_selection.as_mut(), names) { + for name in names.iter() { + if let ast::MetaWord(ref name) = name.node { + sel.insert(name.clone()); + } else { + self.sess.span_err(name.span, "bad macro import"); + } + } + } + } "macro_reexport" => { let names = match attr.meta_item_list() { Some(names) => names, @@ -126,6 +141,11 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { let mut macros = vec![]; let mut registrar = None; + let load_macros = match macro_selection.as_ref() { + Some(sel) => sel.len() != 0 || reexport.len() != 0, + None => true, + }; + if load_macros || load_registrar { let pmd = self.reader.read_plugin_metadata(vi); if load_macros { @@ -137,9 +157,12 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } for mut def in macros.into_iter() { - if reexport.contains(&token::get_ident(def.ident)) { - def.export = true; - } + let name = token::get_ident(def.ident); + def.use_locally = match macro_selection.as_ref() { + None => true, + Some(sel) => sel.contains(&name), + }; + def.export = reexport.contains(&name); self.plugins.macros.push(def); } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e34060a73c154..0f90e31c17eee 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1709,6 +1709,7 @@ pub struct MacroDef { pub span: Span, pub imported_from: Option, pub export: bool, + pub use_locally: bool, pub body: Vec, } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 815159e94c82a..91ae7396ea469 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -574,8 +574,10 @@ impl<'a> ExtCtxt<'a> { if def.export { self.exported_macros.push(def.clone()); } - let ext = macro_rules::compile(self, &def); - self.syntax_env.insert(def.ident.name, ext); + if def.use_locally { + let ext = macro_rules::compile(self, &def); + self.syntax_env.insert(def.ident.name, ext); + } } /// Emit `msg` attached to `sp`, and stop compilation immediately. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 6c2b0610fa037..d3f2e0ea095b6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -636,6 +636,7 @@ pub fn expand_item_mac(it: P, span: it.span, imported_from: None, export: attr::contains_name(it.attrs.as_slice(), "macro_export"), + use_locally: true, body: tts, }; fld.cx.insert_macro(def); diff --git a/src/test/auxiliary/macro_reexport_2_no_use.rs b/src/test/auxiliary/macro_reexport_2_no_use.rs new file mode 100644 index 0000000000000..63142b0a69935 --- /dev/null +++ b/src/test/auxiliary/macro_reexport_2_no_use.rs @@ -0,0 +1,15 @@ +// 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. + +#![crate_type = "dylib"] + +#[macro_reexport(reexported)] +#[no_link] +extern crate macro_reexport_1; diff --git a/src/test/auxiliary/two_macros.rs b/src/test/auxiliary/two_macros.rs new file mode 100644 index 0000000000000..39393b77f25f0 --- /dev/null +++ b/src/test/auxiliary/two_macros.rs @@ -0,0 +1,19 @@ +// 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. + +// force-host + +#![feature(macro_rules)] + +#[macro_export] +macro_rules! macro_one { () => ("one") } + +#[macro_export] +macro_rules! macro_two { () => ("two") } diff --git a/src/test/compile-fail/empty-macro-use.rs b/src/test/compile-fail/empty-macro-use.rs new file mode 100644 index 0000000000000..fbf6287db9444 --- /dev/null +++ b/src/test/compile-fail/empty-macro-use.rs @@ -0,0 +1,19 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use()] +extern crate two_macros; + +pub fn main() { + macro_two!(); //~ ERROR macro undefined +} diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-reexport-not-locally-visible.rs new file mode 100644 index 0000000000000..c8e59f98d3cea --- /dev/null +++ b/src/test/compile-fail/macro-reexport-not-locally-visible.rs @@ -0,0 +1,20 @@ +// 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. + +// aux-build:macro_reexport_1.rs +// ignore-stage1 + +#[macro_reexport(reexported)] +#[no_link] +extern crate macro_reexport_1; + +fn main() { + assert_eq!(reexported!(), 3u); //~ ERROR macro undefined +} diff --git a/src/test/compile-fail/macro-use-bad-args-1.rs b/src/test/compile-fail/macro-use-bad-args-1.rs new file mode 100644 index 0000000000000..a73c4adb71f9f --- /dev/null +++ b/src/test/compile-fail/macro-use-bad-args-1.rs @@ -0,0 +1,15 @@ +// 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_use(foo(bar))] //~ ERROR bad macro import +extern crate std; + +fn main() { +} diff --git a/src/test/compile-fail/macro-use-bad-args-2.rs b/src/test/compile-fail/macro-use-bad-args-2.rs new file mode 100644 index 0000000000000..31efe857605b4 --- /dev/null +++ b/src/test/compile-fail/macro-use-bad-args-2.rs @@ -0,0 +1,15 @@ +// 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_use(foo="bar")] //~ ERROR bad macro import +extern crate std; + +fn main() { +} diff --git a/src/test/compile-fail/macro-use-wrong-name.rs b/src/test/compile-fail/macro-use-wrong-name.rs new file mode 100644 index 0000000000000..4e0486f0db7e9 --- /dev/null +++ b/src/test/compile-fail/macro-use-wrong-name.rs @@ -0,0 +1,19 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_one)] +extern crate two_macros; + +pub fn main() { + macro_two!(); //~ ERROR macro undefined +} diff --git a/src/test/compile-fail/missing-macro-use.rs b/src/test/compile-fail/missing-macro-use.rs new file mode 100644 index 0000000000000..0153d71fb268f --- /dev/null +++ b/src/test/compile-fail/missing-macro-use.rs @@ -0,0 +1,18 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +extern crate two_macros; + +pub fn main() { + macro_two!(); //~ ERROR macro undefined +} diff --git a/src/test/run-pass/macro-reexport-no-intermediate-use.rs b/src/test/run-pass/macro-reexport-no-intermediate-use.rs new file mode 100644 index 0000000000000..77ef9421273ef --- /dev/null +++ b/src/test/run-pass/macro-reexport-no-intermediate-use.rs @@ -0,0 +1,20 @@ +// 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. + +// aux-build:macro_reexport_1.rs +// aux-build:macro_reexport_2_no_use.rs +// ignore-stage1 + +#[macro_use] #[no_link] +extern crate macro_reexport_2_no_use; + +fn main() { + assert_eq!(reexported!(), 3u); +} diff --git a/src/test/run-pass/macro-use-all-and-none.rs b/src/test/run-pass/macro-use-all-and-none.rs new file mode 100644 index 0000000000000..b46910290a8a0 --- /dev/null +++ b/src/test/run-pass/macro-use-all-and-none.rs @@ -0,0 +1,21 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use] +#[macro_use()] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/src/test/run-pass/macro-use-all.rs b/src/test/run-pass/macro-use-all.rs new file mode 100644 index 0000000000000..cf72d2c623044 --- /dev/null +++ b/src/test/run-pass/macro-use-all.rs @@ -0,0 +1,20 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/src/test/run-pass/macro-use-both.rs b/src/test/run-pass/macro-use-both.rs new file mode 100644 index 0000000000000..4b0814bef04b8 --- /dev/null +++ b/src/test/run-pass/macro-use-both.rs @@ -0,0 +1,20 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_one, macro_two)] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +} diff --git a/src/test/run-pass/macro-use-one.rs b/src/test/run-pass/macro-use-one.rs new file mode 100644 index 0000000000000..7911fec94da8b --- /dev/null +++ b/src/test/run-pass/macro-use-one.rs @@ -0,0 +1,19 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_two)] +extern crate two_macros; + +pub fn main() { + macro_two!(); +} diff --git a/src/test/run-pass/two-macro-use.rs b/src/test/run-pass/two-macro-use.rs new file mode 100644 index 0000000000000..51c0b75e8fbe6 --- /dev/null +++ b/src/test/run-pass/two-macro-use.rs @@ -0,0 +1,21 @@ +// 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. + +// aux-build:two_macros.rs +// ignore-stage1 + +#[macro_use(macro_one)] +#[macro_use(macro_two)] +extern crate two_macros; + +pub fn main() { + macro_one!(); + macro_two!(); +}