Skip to content

Commit a8a210b

Browse files
committed
auto merge of #20032 : Manishearth/rust/plugin-loader, r=cmr
`rustc something.rs -L folder_with_plugin_dylib/ -Z extra-plugins=foo` works via this My way of testing this is by cloning https://github.com/Manishearth/rust-clippy, `cargo build`ing it, and then running `rustc examples/box_vec.rs -L target/ -Z extra-plugins=rust_clippy` after editing out the `exern crate rust_clippy` from `box_vec.rs` r? @huonw fixes #15446
2 parents 2f99a41 + 6342aa6 commit a8a210b

File tree

19 files changed

+329
-274
lines changed

19 files changed

+329
-274
lines changed

src/compiletest/header.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ pub struct TestProps {
4242
pub pretty_compare_only: bool,
4343
// Patterns which must not appear in the output of a cfail test.
4444
pub forbid_output: Vec<String>,
45+
// Ignore errors which originate from a command line span
46+
pub ignore_command_line: bool,
4547
}
4648

4749
// Load any test directives embedded in the file
@@ -60,6 +62,8 @@ pub fn load_props(testfile: &Path) -> TestProps {
6062
let mut pretty_mode = None;
6163
let mut pretty_compare_only = false;
6264
let mut forbid_output = Vec::new();
65+
let mut ignore_command_line = false;
66+
6367
iter_header(testfile, |ln| {
6468
match parse_error_pattern(ln) {
6569
Some(ep) => error_patterns.push(ep),
@@ -102,6 +106,10 @@ pub fn load_props(testfile: &Path) -> TestProps {
102106
pretty_compare_only = parse_pretty_compare_only(ln);
103107
}
104108

109+
if !ignore_command_line {
110+
ignore_command_line = parse_ignore_command_line(ln);
111+
}
112+
105113
match parse_aux_build(ln) {
106114
Some(ab) => { aux_builds.push(ab); }
107115
None => {}
@@ -140,6 +148,7 @@ pub fn load_props(testfile: &Path) -> TestProps {
140148
pretty_mode: pretty_mode.unwrap_or("normal".to_string()),
141149
pretty_compare_only: pretty_compare_only,
142150
forbid_output: forbid_output,
151+
ignore_command_line: ignore_command_line,
143152
}
144153
}
145154

@@ -291,6 +300,10 @@ fn parse_pretty_compare_only(line: &str) -> bool {
291300
parse_name_directive(line, "pretty-compare-only")
292301
}
293302

303+
fn parse_ignore_command_line(line: &str) -> bool {
304+
parse_name_directive(line, "ignore-command-line")
305+
}
306+
294307
fn parse_exec_env(line: &str) -> Option<(String, String)> {
295308
parse_name_value_directive(line, "exec-env").map(|nv| {
296309
// nv is either FOO or FOO=BAR

src/compiletest/runtest.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
104104
if !props.error_patterns.is_empty() {
105105
fatal("both error pattern and expected errors specified");
106106
}
107-
check_expected_errors(expected_errors, testfile, &proc_res);
107+
check_expected_errors(props, expected_errors, testfile, &proc_res);
108108
} else {
109109
check_error_patterns(props, testfile, output_to_check.as_slice(), &proc_res);
110110
}
@@ -941,7 +941,8 @@ fn check_forbid_output(props: &TestProps,
941941
}
942942
}
943943

944-
fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
944+
fn check_expected_errors(props: &TestProps,
945+
expected_errors: Vec<errors::ExpectedError> ,
945946
testfile: &Path,
946947
proc_res: &ProcRes) {
947948

@@ -996,6 +997,11 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
996997
was_expected = true;
997998
}
998999

1000+
if line.starts_with("<command line option>") &&
1001+
props.ignore_command_line {
1002+
was_expected = true;
1003+
}
1004+
9991005
if !was_expected && is_compiler_error_or_warning(line) {
10001006
fatal_proc_rec(format!("unexpected compiler error or warning: '{}'",
10011007
line).as_slice(),

src/librustc/metadata/creader.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use syntax::ast;
2626
use syntax::abi;
2727
use syntax::attr;
2828
use syntax::attr::AttrMetaMethods;
29-
use syntax::codemap::{Span, mk_sp};
29+
use syntax::codemap::{COMMAND_LINE_SP, Span, mk_sp};
3030
use syntax::parse;
3131
use syntax::parse::token::InternedString;
3232
use syntax::parse::token;
@@ -445,8 +445,20 @@ impl<'a> CrateReader<'a> {
445445
}
446446

447447
pub fn read_plugin_metadata<'b>(&'b mut self,
448-
vi: &'b ast::ViewItem) -> PluginMetadata<'b> {
449-
let info = self.extract_crate_info(vi).unwrap();
448+
krate: CrateOrString<'b>) -> PluginMetadata<'b> {
449+
let (info, span) = match krate {
450+
CrateOrString::Krate(c) => {
451+
(self.extract_crate_info(c).unwrap(), c.span)
452+
}
453+
CrateOrString::Str(s) => {
454+
(CrateInfo {
455+
name: s.to_string(),
456+
ident: s.to_string(),
457+
id: ast::DUMMY_NODE_ID,
458+
should_link: true,
459+
}, COMMAND_LINE_SP)
460+
}
461+
};
450462
let target_triple = &self.sess.opts.target_triple[];
451463
let is_cross = target_triple != config::host_triple();
452464
let mut should_link = info.should_link && !is_cross;
@@ -455,7 +467,7 @@ impl<'a> CrateReader<'a> {
455467
let name = info.name.clone();
456468
let mut load_ctxt = loader::Context {
457469
sess: self.sess,
458-
span: vi.span,
470+
span: span,
459471
ident: &ident[],
460472
crate_name: &name[],
461473
hash: None,
@@ -486,7 +498,7 @@ impl<'a> CrateReader<'a> {
486498
let metadata = if register {
487499
// Register crate now to avoid double-reading metadata
488500
let (_, cmd, _) = self.register_crate(&None, &info.ident[],
489-
&info.name[], vi.span, library);
501+
&info.name[], span, library);
490502
PMDSource::Registered(cmd)
491503
} else {
492504
// Not registering the crate; just hold on to the metadata
@@ -498,12 +510,18 @@ impl<'a> CrateReader<'a> {
498510
metadata: metadata,
499511
dylib: dylib,
500512
info: info,
501-
vi_span: vi.span,
513+
vi_span: span,
502514
target_only: target_only,
503515
}
504516
}
505517
}
506518

519+
#[derive(Copy)]
520+
pub enum CrateOrString<'a> {
521+
Krate(&'a ast::ViewItem),
522+
Str(&'a str)
523+
}
524+
507525
impl<'a> PluginMetadata<'a> {
508526
/// Read exported macros
509527
pub fn exported_macros(&self) -> Vec<ast::MacroDef> {

src/librustc/middle/infer/region_inference/graphviz.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use middle::ty;
2222
use super::Constraint;
2323
use middle::infer::SubregionOrigin;
2424
use middle::infer::region_inference::RegionVarBindings;
25-
use session::config;
2625
use util::nodemap::{FnvHashMap, FnvHashSet};
2726
use util::ppaux::Repr;
2827

@@ -55,7 +54,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
5554
subject_node: ast::NodeId) {
5655
let tcx = region_vars.tcx;
5756

58-
if !region_vars.tcx.sess.debugging_opt(config::PRINT_REGION_GRAPH) {
57+
if !region_vars.tcx.sess.opts.debugging_opts.print_region_graph {
5958
return;
6059
}
6160

src/librustc/plugin/load.rs

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! Used by `rustc` when loading a plugin, or a crate with exported macros.
1212
1313
use session::Session;
14-
use metadata::creader::CrateReader;
14+
use metadata::creader::{CrateOrString, CrateReader};
1515
use plugin::registry::Registry;
1616

1717
use std::mem;
@@ -44,11 +44,11 @@ pub struct Plugins {
4444
pub registrars: Vec<PluginRegistrar>,
4545
}
4646

47-
struct PluginLoader<'a> {
47+
pub struct PluginLoader<'a> {
4848
sess: &'a Session,
4949
span_whitelist: HashSet<Span>,
5050
reader: CrateReader<'a>,
51-
plugins: Plugins,
51+
pub plugins: Plugins,
5252
}
5353

5454
impl<'a> PluginLoader<'a> {
@@ -67,7 +67,7 @@ impl<'a> PluginLoader<'a> {
6767

6868
/// Read plugin metadata and dynamically load registrar functions.
6969
pub fn load_plugins(sess: &Session, krate: &ast::Crate,
70-
addl_plugins: Option<Plugins>) -> Plugins {
70+
addl_plugins: Option<Vec<String>>) -> Plugins {
7171
let mut loader = PluginLoader::new(sess);
7272

7373
// We need to error on `#[macro_use] extern crate` when it isn't at the
@@ -79,19 +79,14 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
7979

8080
visit::walk_crate(&mut loader, krate);
8181

82-
let mut plugins = loader.plugins;
83-
84-
match addl_plugins {
85-
Some(addl_plugins) => {
86-
// Add in the additional plugins requested by the frontend
87-
let Plugins { macros: addl_macros, registrars: addl_registrars } = addl_plugins;
88-
plugins.macros.extend(addl_macros.into_iter());
89-
plugins.registrars.extend(addl_registrars.into_iter());
82+
if let Some(plugins) = addl_plugins {
83+
for plugin in plugins.iter() {
84+
loader.load_plugin(CrateOrString::Str(plugin.as_slice()),
85+
None, None, None)
9086
}
91-
None => ()
9287
}
9388

94-
return plugins;
89+
return loader.plugins;
9590
}
9691

9792
// note that macros aren't expanded yet, and therefore macros can't add plugins.
@@ -160,22 +155,39 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
160155
}
161156
}
162157

158+
self.load_plugin(CrateOrString::Krate(vi), plugin_attr, macro_selection, Some(reexport))
159+
}
160+
161+
fn visit_mac(&mut self, _: &ast::Mac) {
162+
// bummer... can't see plugins inside macros.
163+
// do nothing.
164+
}
165+
}
166+
167+
impl<'a> PluginLoader<'a> {
168+
pub fn load_plugin<'b>(&mut self,
169+
c: CrateOrString<'b>,
170+
plugin_attr: Option<P<ast::MetaItem>>,
171+
macro_selection: Option<HashSet<token::InternedString>>,
172+
reexport: Option<HashSet<token::InternedString>>) {
163173
let mut macros = vec![];
164174
let mut registrar = None;
165175

166-
let load_macros = match macro_selection.as_ref() {
167-
Some(sel) => sel.len() != 0 || reexport.len() != 0,
168-
None => true,
176+
let load_macros = match (macro_selection.as_ref(), reexport.as_ref()) {
177+
(Some(sel), Some(re)) => sel.len() != 0 || re.len() != 0,
178+
_ => true,
169179
};
170180
let load_registrar = plugin_attr.is_some();
171181

172-
if load_macros && !self.span_whitelist.contains(&vi.span) {
173-
self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
174-
the crate root");
175-
}
182+
if let CrateOrString::Krate(vi) = c {
183+
if load_macros && !self.span_whitelist.contains(&vi.span) {
184+
self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
185+
the crate root");
186+
}
187+
}
176188

177189
if load_macros || load_registrar {
178-
let pmd = self.reader.read_plugin_metadata(vi);
190+
let pmd = self.reader.read_plugin_metadata(c);
179191
if load_macros {
180192
macros = pmd.exported_macros();
181193
}
@@ -190,29 +202,26 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
190202
None => true,
191203
Some(sel) => sel.contains(&name),
192204
};
193-
def.export = reexport.contains(&name);
205+
def.export = if let Some(ref re) = reexport {
206+
re.contains(&name)
207+
} else {
208+
false // Don't reexport macros from crates loaded from the command line
209+
};
194210
self.plugins.macros.push(def);
195211
}
196212

197213
if let Some((lib, symbol)) = registrar {
198-
let fun = self.dylink_registrar(vi, lib, symbol);
214+
let fun = self.dylink_registrar(c, lib, symbol);
199215
self.plugins.registrars.push(PluginRegistrar {
200216
fun: fun,
201217
args: plugin_attr.unwrap(),
202218
});
203219
}
204220
}
205221

206-
fn visit_mac(&mut self, _: &ast::Mac) {
207-
// bummer... can't see plugins inside macros.
208-
// do nothing.
209-
}
210-
}
211-
212-
impl<'a> PluginLoader<'a> {
213222
// Dynamically link a registrar function into the compiler process.
214-
fn dylink_registrar(&mut self,
215-
vi: &ast::ViewItem,
223+
fn dylink_registrar<'b>(&mut self,
224+
c: CrateOrString<'b>,
216225
path: Path,
217226
symbol: String) -> PluginRegistrarFun {
218227
// Make sure the path contains a / or the linker will search for it.
@@ -223,7 +232,13 @@ impl<'a> PluginLoader<'a> {
223232
// this is fatal: there are almost certainly macros we need
224233
// inside this crate, so continue would spew "macro undefined"
225234
// errors
226-
Err(err) => self.sess.span_fatal(vi.span, &err[])
235+
Err(err) => {
236+
if let CrateOrString::Krate(cr) = c {
237+
self.sess.span_fatal(cr.span, &err[])
238+
} else {
239+
self.sess.fatal(&err[])
240+
}
241+
}
227242
};
228243

229244
unsafe {
@@ -233,7 +248,13 @@ impl<'a> PluginLoader<'a> {
233248
mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
234249
}
235250
// again fatal if we can't register macros
236-
Err(err) => self.sess.span_fatal(vi.span, &err[])
251+
Err(err) => {
252+
if let CrateOrString::Krate(cr) = c {
253+
self.sess.span_fatal(cr.span, &err[])
254+
} else {
255+
self.sess.fatal(&err[])
256+
}
257+
}
237258
};
238259

239260
// Intentionally leak the dynamic library. We can't ever unload it

0 commit comments

Comments
 (0)