Skip to content

Commit b7683fc

Browse files
author
Keegan McAllister
committed
Warn when linking a plugin into a non-plugin crate
Fixes #22202.
1 parent 6864792 commit b7683fc

File tree

8 files changed

+152
-1
lines changed

8 files changed

+152
-1
lines changed

src/doc/trpl/plugins.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ If present, arguments passed as `#![plugin(foo(... args ...))]` are not
3939
interpreted by rustc itself. They are provided to the plugin through the
4040
`Registry`'s [`args` method](../rustc/plugin/registry/struct.Registry.html#method.args).
4141

42+
In the vast majority of cases, a plugin should *only* be used through
43+
`#![plugin]` and not through an `extern crate` item. Linking a plugin would
44+
pull in all of libsyntax and librustc as dependencies of your crate. This is
45+
generally unwanted unless you are building another plugin. The
46+
`plugin_as_library` lint checks these guidelines.
47+
48+
The usual practice is to put compiler plugins in their own crate, separate from
49+
any `macro_rules!` macros or ordinary Rust code meant to be used by consumers
50+
of a library.
51+
4252
# Syntax extensions
4353

4454
Plugins can extend Rust's syntax in various ways. One kind of syntax extension

src/librustc/lint/builtin.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
//! a `pub fn new()`.
2727
use self::MethodContext::*;
2828

29-
use metadata::csearch;
29+
use metadata::{csearch, decoder};
3030
use middle::def::*;
3131
use middle::subst::Substs;
3232
use middle::ty::{self, Ty};
@@ -1963,6 +1963,48 @@ impl LintPass for UnconditionalRecursion {
19631963
}
19641964
}
19651965

1966+
declare_lint! {
1967+
PLUGIN_AS_LIBRARY,
1968+
Warn,
1969+
"compiler plugin used as ordinary library in non-plugin crate"
1970+
}
1971+
1972+
#[derive(Copy)]
1973+
pub struct PluginAsLibrary;
1974+
1975+
impl LintPass for PluginAsLibrary {
1976+
fn get_lints(&self) -> LintArray {
1977+
lint_array![PLUGIN_AS_LIBRARY]
1978+
}
1979+
1980+
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
1981+
if cx.sess().plugin_registrar_fn.get().is_some() {
1982+
// We're compiling a plugin; it's fine to link other plugins.
1983+
return;
1984+
}
1985+
1986+
match it.node {
1987+
ast::ItemExternCrate(..) => (),
1988+
_ => return,
1989+
};
1990+
1991+
let md = match cx.sess().cstore.find_extern_mod_stmt_cnum(it.id) {
1992+
Some(cnum) => cx.sess().cstore.get_crate_data(cnum),
1993+
None => {
1994+
// Probably means we aren't linking the crate for some reason.
1995+
//
1996+
// Not sure if / when this could happen.
1997+
return;
1998+
}
1999+
};
2000+
2001+
if decoder::get_plugin_registrar_fn(md.data()).is_some() {
2002+
cx.span_lint(PLUGIN_AS_LIBRARY, it.span,
2003+
"compiler plugin used as an ordinary library");
2004+
}
2005+
}
2006+
}
2007+
19662008
declare_lint! {
19672009
pub UNUSED_IMPORTS,
19682010
Warn,

src/librustc/lint/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ impl LintStore {
214214
Stability,
215215
UnconditionalRecursion,
216216
InvalidNoMangleItems,
217+
PluginAsLibrary,
217218
);
218219

219220
add_builtin_with_new!(sess,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// force-host
12+
13+
#![feature(plugin_registrar)]
14+
#![deny(plugin_as_library)] // should have no effect in a plugin crate
15+
16+
extern crate macro_crate_test;
17+
extern crate rustc;
18+
19+
use rustc::plugin::Registry;
20+
21+
#[plugin_registrar]
22+
pub fn plugin_registrar(_: &mut Registry) { }
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:macro_crate_test.rs
12+
// ignore-stage1
13+
// ignore-cross-compile
14+
//
15+
// macro_crate_test will not compile on a cross-compiled target because
16+
// libsyntax is not compiled for it.
17+
18+
#![deny(plugin_as_library)]
19+
20+
extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
21+
22+
fn main() { }
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:macro_crate_test.rs
12+
// ignore-stage1
13+
// ignore-cross-compile
14+
//
15+
// macro_crate_test will not compile on a cross-compiled target because
16+
// libsyntax is not compiled for it.
17+
18+
#![deny(plugin_as_library)]
19+
#![feature(plugin)]
20+
#![plugin(macro_crate_test)]
21+
22+
extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
23+
24+
fn main() {
25+
assert_eq!(1, make_a_1!());
26+
macro_crate_test::foo();
27+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:macro_crate_test.rs
12+
// aux-build:plugin_with_plugin_lib.rs
13+
// ignore-stage1
14+
// ignore-cross-compile
15+
//
16+
// macro_crate_test will not compile on a cross-compiled target because
17+
// libsyntax is not compiled for it.
18+
19+
#![deny(plugin_as_library)]
20+
#![feature(plugin)]
21+
#![plugin(macro_crate_test)]
22+
#![plugin(plugin_with_plugin_lib)]
23+
24+
fn main() {
25+
assert_eq!(1, make_a_1!());
26+
}

src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
// macro_crate_test will not compile on a cross-compiled target because
1616
// libsyntax is not compiled for it.
1717

18+
#![allow(plugin_as_library)]
1819
#![feature(plugin)]
1920
#![plugin(macro_crate_test)]
2021

0 commit comments

Comments
 (0)