]> git.lizzy.rs Git - rust.git/commitdiff
Warn when linking a plugin into a non-plugin crate
authorKeegan McAllister <kmcallister@mozilla.com>
Thu, 12 Feb 2015 06:33:07 +0000 (22:33 -0800)
committerKeegan McAllister <kmcallister@mozilla.com>
Thu, 12 Feb 2015 20:44:31 +0000 (12:44 -0800)
Fixes #22202.

src/doc/trpl/plugins.md
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/test/auxiliary/plugin_with_plugin_lib.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/plugin-plus-extern-crate.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/plugin-lib-ok-in-plugin.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs

index 3dea1a66ffd72519732fcf64dafa452ed83ed8ad..79502f3cd17f755768cabac2c00c36c2f594f03a 100644 (file)
@@ -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
index a415ff3ed7165cbe56d40a6318dc2f09720d438c..74e921acdb404c011bc9c23960e731a361bbbdac 100644 (file)
@@ -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};
@@ -1963,6 +1963,48 @@ fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
+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,
index 616af79326d9a5445633ee4d9372c7f564c4ff20..42a6861f452a66f95d6f0f0c301979165a92264a 100644 (file)
@@ -214,6 +214,7 @@ macro_rules! add_lint_group {
                      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 (file)
index 0000000..cfc8c01
--- /dev/null
@@ -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 (file)
index 0000000..c5169b6
--- /dev/null
@@ -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 (file)
index 0000000..3dfd883
--- /dev/null
@@ -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 (file)
index 0000000..c612ee7
--- /dev/null
@@ -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!());
+}
index 0c27dba9c627f72dffe91c140e4991540d6032a5..d1ce83f26778847cbb484ea8abc392d9cf9425c4 100644 (file)
@@ -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)]