Fixes #22202.
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
//! 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};
}
}
+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,
Stability,
UnconditionalRecursion,
InvalidNoMangleItems,
+ PluginAsLibrary,
);
add_builtin_with_new!(sess,
--- /dev/null
+// 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) { }
--- /dev/null
+// 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() { }
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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!());
+}
// 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)]