diff options
| author | Keegan McAllister <kmcallister@mozilla.com> | 2015-02-11 22:33:07 -0800 |
|---|---|---|
| committer | Keegan McAllister <kmcallister@mozilla.com> | 2015-02-12 12:44:31 -0800 |
| commit | b7683fc02b35cafc849b7097556f4f67c3adcfe9 (patch) | |
| tree | 60abc58eaaa004f2e5954e7e4f3858403b6abec8 | |
| parent | 6864792df002a4430634ea6ae096dd7e524560c2 (diff) | |
| download | rust-b7683fc02b35cafc849b7097556f4f67c3adcfe9.tar.gz rust-b7683fc02b35cafc849b7097556f4f67c3adcfe9.zip | |
Warn when linking a plugin into a non-plugin crate
Fixes #22202.
| -rw-r--r-- | src/doc/trpl/plugins.md | 10 | ||||
| -rw-r--r-- | src/librustc/lint/builtin.rs | 44 | ||||
| -rw-r--r-- | src/librustc/lint/context.rs | 1 | ||||
| -rw-r--r-- | src/test/auxiliary/plugin_with_plugin_lib.rs | 22 | ||||
| -rw-r--r-- | src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs | 22 | ||||
| -rw-r--r-- | src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs | 27 | ||||
| -rw-r--r-- | src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs | 26 | ||||
| -rw-r--r-- | src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs | 1 |
8 files changed, 152 insertions, 1 deletions
diff --git a/src/doc/trpl/plugins.md b/src/doc/trpl/plugins.md index 3dea1a66ffd..79502f3cd17 100644 --- a/src/doc/trpl/plugins.md +++ b/src/doc/trpl/plugins.md @@ -39,6 +39,16 @@ If present, arguments passed as `#![plugin(foo(... args ...))]` are not interpreted by rustc itself. They are provided to the plugin through the `Registry`'s [`args` method](../rustc/plugin/registry/struct.Registry.html#method.args). +In the vast majority of cases, a plugin should *only* be used through +`#![plugin]` and not through an `extern crate` item. Linking a plugin would +pull in all of libsyntax and librustc as dependencies of your crate. This is +generally unwanted unless you are building another plugin. The +`plugin_as_library` lint checks these guidelines. + +The usual practice is to put compiler plugins in their own crate, separate from +any `macro_rules!` macros or ordinary Rust code meant to be used by consumers +of a library. + # Syntax extensions Plugins can extend Rust's syntax in various ways. One kind of syntax extension diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index a415ff3ed71..74e921acdb4 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -26,7 +26,7 @@ //! a `pub fn new()`. use self::MethodContext::*; -use metadata::csearch; +use metadata::{csearch, decoder}; use middle::def::*; use middle::subst::Substs; use middle::ty::{self, Ty}; @@ -1964,6 +1964,48 @@ impl LintPass for UnconditionalRecursion { } declare_lint! { + PLUGIN_AS_LIBRARY, + Warn, + "compiler plugin used as ordinary library in non-plugin crate" +} + +#[derive(Copy)] +pub struct PluginAsLibrary; + +impl LintPass for PluginAsLibrary { + fn get_lints(&self) -> LintArray { + lint_array![PLUGIN_AS_LIBRARY] + } + + fn check_item(&mut self, cx: &Context, it: &ast::Item) { + if cx.sess().plugin_registrar_fn.get().is_some() { + // We're compiling a plugin; it's fine to link other plugins. + return; + } + + match it.node { + ast::ItemExternCrate(..) => (), + _ => return, + }; + + let md = match cx.sess().cstore.find_extern_mod_stmt_cnum(it.id) { + Some(cnum) => cx.sess().cstore.get_crate_data(cnum), + None => { + // Probably means we aren't linking the crate for some reason. + // + // Not sure if / when this could happen. + return; + } + }; + + if decoder::get_plugin_registrar_fn(md.data()).is_some() { + cx.span_lint(PLUGIN_AS_LIBRARY, it.span, + "compiler plugin used as an ordinary library"); + } + } +} + +declare_lint! { pub UNUSED_IMPORTS, Warn, "imports that are never used" diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 616af79326d..42a6861f452 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -214,6 +214,7 @@ impl LintStore { Stability, UnconditionalRecursion, InvalidNoMangleItems, + PluginAsLibrary, ); add_builtin_with_new!(sess, diff --git a/src/test/auxiliary/plugin_with_plugin_lib.rs b/src/test/auxiliary/plugin_with_plugin_lib.rs new file mode 100644 index 00000000000..cfc8c015324 --- /dev/null +++ b/src/test/auxiliary/plugin_with_plugin_lib.rs @@ -0,0 +1,22 @@ +// 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. + +// force-host + +#![feature(plugin_registrar)] +#![deny(plugin_as_library)] // should have no effect in a plugin crate + +extern crate macro_crate_test; +extern crate rustc; + +use rustc::plugin::Registry; + +#[plugin_registrar] +pub fn plugin_registrar(_: &mut Registry) { } diff --git a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs new file mode 100644 index 00000000000..c5169b61a2b --- /dev/null +++ b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs @@ -0,0 +1,22 @@ +// Copyright 2013-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. + +// aux-build:macro_crate_test.rs +// ignore-stage1 +// ignore-cross-compile +// +// macro_crate_test will not compile on a cross-compiled target because +// libsyntax is not compiled for it. + +#![deny(plugin_as_library)] + +extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library + +fn main() { } diff --git a/src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs b/src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs new file mode 100644 index 00000000000..3dfd8838ebe --- /dev/null +++ b/src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs @@ -0,0 +1,27 @@ +// Copyright 2013-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. + +// aux-build:macro_crate_test.rs +// ignore-stage1 +// ignore-cross-compile +// +// macro_crate_test will not compile on a cross-compiled target because +// libsyntax is not compiled for it. + +#![deny(plugin_as_library)] +#![feature(plugin)] +#![plugin(macro_crate_test)] + +extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library + +fn main() { + assert_eq!(1, make_a_1!()); + macro_crate_test::foo(); +} diff --git a/src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs b/src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs new file mode 100644 index 00000000000..c612ee75651 --- /dev/null +++ b/src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs @@ -0,0 +1,26 @@ +// Copyright 2013-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. + +// aux-build:macro_crate_test.rs +// aux-build:plugin_with_plugin_lib.rs +// ignore-stage1 +// ignore-cross-compile +// +// macro_crate_test will not compile on a cross-compiled target because +// libsyntax is not compiled for it. + +#![deny(plugin_as_library)] +#![feature(plugin)] +#![plugin(macro_crate_test)] +#![plugin(plugin_with_plugin_lib)] + +fn main() { + assert_eq!(1, make_a_1!()); +} diff --git a/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs b/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs index 0c27dba9c62..d1ce83f2677 100644 --- a/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs +++ b/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs @@ -15,6 +15,7 @@ // macro_crate_test will not compile on a cross-compiled target because // libsyntax is not compiled for it. +#![allow(plugin_as_library)] #![feature(plugin)] #![plugin(macro_crate_test)] |
