From 6d15c6749c30d9077c6e12af3be64c5f68fafcff Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sat, 24 May 2014 16:16:10 -0700 Subject: Implement #[plugin_registrar] See RFC 22. [breaking-change] --- src/libsyntax/ext/base.rs | 19 ++---- src/libsyntax/ext/expand.rs | 152 ++++++++--------------------------------- src/libsyntax/ext/registrar.rs | 58 ---------------- src/libsyntax/lib.rs | 1 - 4 files changed, 34 insertions(+), 196 deletions(-) delete mode 100644 src/libsyntax/ext/registrar.rs (limited to 'src/libsyntax') diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 521b7ee0063..e81421cff04 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -95,9 +95,6 @@ impl IdentMacroExpander for BasicIdentMacroExpander { pub type IdentMacroExpanderFn = fn(&mut ExtCtxt, Span, ast::Ident, Vec) -> Box; -pub type MacroCrateRegistrationFun = - fn(|ast::Name, SyntaxExtension|); - /// The result of a macro expansion. The return values of the various /// methods are spliced into the AST at the callsite of the macro (or /// just into the compiler's internal macro table, for `make_def`). @@ -268,6 +265,8 @@ pub enum SyntaxExtension { IdentTT(Box, Option), } +pub type NamedSyntaxExtension = (Name, SyntaxExtension); + pub struct BlockInfo { // should macros escape from this scope? pub macros_escape: bool, @@ -392,16 +391,6 @@ pub fn syntax_expander_table() -> SyntaxEnv { syntax_expanders } -pub struct MacroCrate { - pub lib: Option, - pub macros: Vec, - pub registrar_symbol: Option, -} - -pub trait CrateLoader { - fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate; -} - // One of these is made during expansion and incrementally updated as we go; // when a macro expansion occurs, the resulting nodes have the backtrace() // -> expn_info of their expansion context stored into their span. @@ -409,7 +398,7 @@ pub struct ExtCtxt<'a> { pub parse_sess: &'a parse::ParseSess, pub cfg: ast::CrateConfig, pub backtrace: Option<@ExpnInfo>, - pub ecfg: expand::ExpansionConfig<'a>, + pub ecfg: expand::ExpansionConfig, pub mod_path: Vec , pub trace_mac: bool, @@ -417,7 +406,7 @@ pub struct ExtCtxt<'a> { impl<'a> ExtCtxt<'a> { pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig, - ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> { + ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> { ExtCtxt { parse_sess: parse_sess, cfg: cfg, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 03001acc5d0..bb335e7bed0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -29,10 +29,6 @@ use visit; use visit::Visitor; use util::small_vector::SmallVector; -use std::mem; -use std::os; -use std::unstable::dynamic_lib::DynamicLibrary; - pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr { match e.node { // expr_mac should really be expr_ext or something; it's the @@ -497,96 +493,6 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander) return items; } -// load macros from syntax-phase crates -pub fn expand_view_item(vi: &ast::ViewItem, - fld: &mut MacroExpander) - -> ast::ViewItem { - match vi.node { - ast::ViewItemExternCrate(..) => { - let should_load = vi.attrs.iter().any(|attr| { - attr.check_name("phase") && - attr.meta_item_list().map_or(false, |phases| { - attr::contains_name(phases, "syntax") - }) - }); - - if should_load { - load_extern_macros(vi, fld); - } - } - ast::ViewItemUse(_) => {} - } - - noop_fold_view_item(vi, fld) -} - -fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) { - let MacroCrate { lib, macros, registrar_symbol } = - fld.cx.ecfg.loader.load_crate(krate); - - let crate_name = match krate.node { - ast::ViewItemExternCrate(name, _, _) => name, - _ => unreachable!() - }; - let name = format!("<{} macros>", token::get_ident(crate_name)); - let name = name.to_string(); - - for source in macros.iter() { - let item = parse::parse_item_from_source_str(name.clone(), - (*source).clone(), - fld.cx.cfg(), - fld.cx.parse_sess()) - .expect("expected a serialized item"); - expand_item_mac(item, fld); - } - - let path = match lib { - Some(path) => path, - None => return - }; - // Make sure the path contains a / or the linker will search for it. - let path = os::make_absolute(&path); - - let registrar = match registrar_symbol { - Some(registrar) => registrar, - None => return - }; - - debug!("load_extern_macros: mapped crate {} to path {} and registrar {:s}", - crate_name, path.display(), registrar); - - let lib = match DynamicLibrary::open(Some(&path)) { - Ok(lib) => lib, - // this is fatal: there are almost certainly macros we need - // inside this crate, so continue would spew "macro undefined" - // errors - Err(err) => fld.cx.span_fatal(krate.span, err.as_slice()) - }; - - unsafe { - let registrar: MacroCrateRegistrationFun = - match lib.symbol(registrar.as_slice()) { - Ok(registrar) => registrar, - // again fatal if we can't register macros - Err(err) => fld.cx.span_fatal(krate.span, err.as_slice()) - }; - registrar(|name, extension| { - let extension = match extension { - NormalTT(ext, _) => NormalTT(ext, Some(krate.span)), - IdentTT(ext, _) => IdentTT(ext, Some(krate.span)), - ItemDecorator(ext) => ItemDecorator(ext), - ItemModifier(ext) => ItemModifier(ext), - }; - fld.extsbox.insert(name, extension); - }); - - // Intentionally leak the dynamic library. We can't ever unload it - // since the library can do things that will outlive the expansion - // phase (e.g. make an @-box cycle or launch a task). - mem::forget(lib); - } -} - // expand a stmt pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> { // why the copying here and not in expand_expr? @@ -969,10 +875,6 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { expand_item(item, self) } - fn fold_view_item(&mut self, vi: &ast::ViewItem) -> ast::ViewItem { - expand_view_item(vi, self) - } - fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<@ast::Stmt> { expand_stmt(stmt, self) } @@ -986,14 +888,20 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { } } -pub struct ExpansionConfig<'a> { - pub loader: &'a mut CrateLoader, +pub struct ExpansionConfig { pub deriving_hash_type_parameter: bool, pub crate_id: CrateId, } +pub struct ExportedMacros { + pub crate_name: Ident, + pub macros: Vec, +} + pub fn expand_crate(parse_sess: &parse::ParseSess, cfg: ExpansionConfig, + macros: Vec, + user_exts: Vec, c: Crate) -> Crate { let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); let mut expander = MacroExpander { @@ -1001,6 +909,24 @@ pub fn expand_crate(parse_sess: &parse::ParseSess, cx: &mut cx, }; + for ExportedMacros { crate_name, macros } in macros.move_iter() { + let name = format!("<{} macros>", token::get_ident(crate_name)) + .into_string(); + + for source in macros.move_iter() { + let item = parse::parse_item_from_source_str(name.clone(), + source, + expander.cx.cfg(), + expander.cx.parse_sess()) + .expect("expected a serialized item"); + expand_item_mac(item, &mut expander); + } + } + + for (name, extension) in user_exts.move_iter() { + expander.extsbox.insert(name, extension); + } + let ret = expander.fold_crate(c); parse_sess.span_diagnostic.handler().abort_if_errors(); return ret; @@ -1093,7 +1019,6 @@ mod test { use attr; use codemap; use codemap::Spanned; - use ext::base::{CrateLoader, MacroCrate}; use ext::mtwt; use parse; use parse::token; @@ -1137,14 +1062,6 @@ mod test { } } - struct ErrLoader; - - impl CrateLoader for ErrLoader { - fn load_crate(&mut self, _: &ast::ViewItem) -> MacroCrate { - fail!("lolwut") - } - } - // these following tests are quite fragile, in that they don't test what // *kind* of failure occurs. @@ -1159,13 +1076,11 @@ mod test { src, Vec::new(), &sess); // should fail: - let mut loader = ErrLoader; let cfg = ::syntax::ext::expand::ExpansionConfig { - loader: &mut loader, deriving_hash_type_parameter: false, crate_id: from_str("test").unwrap(), }; - expand_crate(&sess,cfg,crate_ast); + expand_crate(&sess,cfg,vec!(),vec!(),crate_ast); } // make sure that macros can leave scope for modules @@ -1178,14 +1093,11 @@ mod test { "".to_string(), src, Vec::new(), &sess); - // should fail: - let mut loader = ErrLoader; let cfg = ::syntax::ext::expand::ExpansionConfig { - loader: &mut loader, deriving_hash_type_parameter: false, crate_id: from_str("test").unwrap(), }; - expand_crate(&sess,cfg,crate_ast); + expand_crate(&sess,cfg,vec!(),vec!(),crate_ast); } // macro_escape modules shouldn't cause macros to leave scope @@ -1198,13 +1110,11 @@ mod test { src, Vec::new(), &sess); // should fail: - let mut loader = ErrLoader; let cfg = ::syntax::ext::expand::ExpansionConfig { - loader: &mut loader, deriving_hash_type_parameter: false, crate_id: from_str("test").unwrap(), }; - expand_crate(&sess, cfg, crate_ast); + expand_crate(&sess, cfg, vec!(), vec!(), crate_ast); } #[test] fn test_contains_flatten (){ @@ -1237,13 +1147,11 @@ mod test { let ps = parse::new_parse_sess(); let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod(); // the cfg argument actually does matter, here... - let mut loader = ErrLoader; let cfg = ::syntax::ext::expand::ExpansionConfig { - loader: &mut loader, deriving_hash_type_parameter: false, crate_id: from_str("test").unwrap(), }; - expand_crate(&ps,cfg,crate_ast) + expand_crate(&ps,cfg,vec!(),vec!(),crate_ast) } //fn expand_and_resolve(crate_str: @str) -> ast::crate { diff --git a/src/libsyntax/ext/registrar.rs b/src/libsyntax/ext/registrar.rs deleted file mode 100644 index b76708147e1..00000000000 --- a/src/libsyntax/ext/registrar.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2012-2013 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use ast; -use attr; -use codemap::Span; -use diagnostic; -use visit; -use visit::Visitor; - -struct MacroRegistrarContext { - registrars: Vec<(ast::NodeId, Span)> , -} - -impl Visitor<()> for MacroRegistrarContext { - fn visit_item(&mut self, item: &ast::Item, _: ()) { - match item.node { - ast::ItemFn(..) => { - if attr::contains_name(item.attrs.as_slice(), - "macro_registrar") { - self.registrars.push((item.id, item.span)); - } - } - _ => {} - } - - visit::walk_item(self, item, ()); - } -} - -pub fn find_macro_registrar(diagnostic: &diagnostic::SpanHandler, - krate: &ast::Crate) -> Option { - let mut ctx = MacroRegistrarContext { registrars: Vec::new() }; - visit::walk_crate(&mut ctx, krate, ()); - - match ctx.registrars.len() { - 0 => None, - 1 => { - let (node_id, _) = ctx.registrars.pop().unwrap(); - Some(node_id) - }, - _ => { - diagnostic.handler().err("multiple macro registration functions found"); - for &(_, span) in ctx.registrars.iter() { - diagnostic.span_note(span, "one is here"); - } - diagnostic.handler().abort_if_errors(); - unreachable!(); - } - } -} diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 1ab420eb69b..7fe67ad6f87 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -74,7 +74,6 @@ pub mod ext { pub mod asm; pub mod base; pub mod expand; - pub mod registrar; pub mod quote; -- cgit 1.4.1-3-g733a5 From ffb2f12ed89213f96561dfbece0751ac870e2c40 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Sat, 24 May 2014 21:15:16 -0700 Subject: Use phase(plugin) in bootstrap crates Do this to avoid warnings on post-stage0 builds. --- src/compiletest/compiletest.rs | 10 ++++++++-- src/liballoc/lib.rs | 12 ++++++++++-- src/libcollections/lib.rs | 16 +++++++++++++--- src/libflate/lib.rs | 3 ++- src/libgetopts/lib.rs | 3 ++- src/librand/lib.rs | 19 +++++++++++++++++-- src/librustc/lib.rs | 5 +++++ src/librustdoc/lib.rs | 10 ++++++++-- src/librustrt/lib.rs | 10 +++++++++- src/libserialize/lib.rs | 6 ++++++ src/libstd/lib.rs | 3 ++- src/libsync/lib.rs | 5 ++++- src/libsyntax/lib.rs | 7 +++++++ src/libterm/lib.rs | 3 ++- src/libtime/lib.rs | 4 +++- 15 files changed, 98 insertions(+), 18 deletions(-) (limited to 'src/libsyntax') diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 8fcad94ee1c..de0ca4971f5 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -18,11 +18,17 @@ extern crate test; extern crate getopts; -#[phase(link, syntax)] -extern crate log; extern crate green; extern crate rustuv; +#[cfg(stage0)] +#[phase(syntax, link)] +extern crate log; + +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate log; + extern crate regex; use std::os; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ca7ed6f4ba0..7e2c9a75fad 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,8 +70,14 @@ #![no_std] #![feature(phase)] +#[cfg(stage0)] #[phase(syntax, link)] extern crate core; + +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate core; + extern crate libc; @@ -80,8 +86,10 @@ extern crate libc; #[cfg(test)] extern crate debug; #[cfg(test)] extern crate sync; #[cfg(test)] extern crate native; -#[cfg(test)] #[phase(syntax, link)] extern crate std; -#[cfg(test)] #[phase(syntax, link)] extern crate log; +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std; +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log; // Heaps provided for low-level allocation strategies diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 602ecf39a83..a114755a0ed 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -23,14 +23,24 @@ #![feature(macro_rules, managed_boxes, default_type_params, phase, globs)] #![no_std] -#[phase(syntax, link)] extern crate core; extern crate alloc; +#[cfg(stage0)] +#[phase(syntax, link)] +extern crate core; + +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate core; + #[cfg(test)] extern crate native; #[cfg(test)] extern crate test; #[cfg(test)] extern crate debug; -#[cfg(test)] #[phase(syntax, link)] extern crate std; -#[cfg(test)] #[phase(syntax, link)] extern crate log; + +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std; +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log; use core::prelude::*; diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 8bfd2d867c1..8d8fe8ffe8c 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -28,7 +28,8 @@ Simple [DEFLATE][def]-based compression. This is a wrapper around the #![feature(phase)] #![deny(deprecated_owned_vector)] -#[cfg(test)] #[phase(syntax, link)] extern crate log; +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log; extern crate libc; diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 10584223486..dec62265516 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -91,7 +91,8 @@ #![deny(deprecated_owned_vector)] #[cfg(test)] extern crate debug; -#[cfg(test)] #[phase(syntax, link)] extern crate log; +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log; use std::cmp::PartialEq; use std::result::{Err, Ok}; diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 7a12dcf9f7f..1f7216fc1a3 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -28,13 +28,28 @@ #![no_std] #![experimental] +#[cfg(stage0)] #[phase(syntax, link)] extern crate core; +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate core; + +#[cfg(test, stage0)] +#[phase(syntax, link)] extern crate std; + +#[cfg(test, stage0)] +#[phase(syntax, link)] extern crate log; + +#[cfg(test, not(stage0))] +#[phase(plugin, link)] extern crate std; + +#[cfg(test, not(stage0))] +#[phase(plugin, link)] extern crate log; + #[cfg(test)] extern crate native; #[cfg(test)] extern crate debug; -#[cfg(test)] #[phase(syntax, link)] extern crate std; -#[cfg(test)] #[phase(syntax, link)] extern crate log; use core::prelude::*; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b82dace62ef..bdbb1a98ac5 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -42,9 +42,14 @@ extern crate sync; extern crate syntax; extern crate time; +#[cfg(stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate log; + pub mod middle { pub mod def; pub mod trans; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e623d54675c..05875f59fbe 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -19,8 +19,6 @@ extern crate debug; extern crate getopts; extern crate libc; -#[phase(syntax, link)] -extern crate log; extern crate rustc; extern crate serialize; extern crate sync; @@ -28,6 +26,14 @@ extern crate syntax; extern crate testing = "test"; extern crate time; +#[cfg(stage0)] +#[phase(syntax, link)] +extern crate log; + +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate log; + use std::io; use std::io::{File, MemWriter}; use std::str; diff --git a/src/librustrt/lib.rs b/src/librustrt/lib.rs index 3158687c6ab..bb57f5c038c 100644 --- a/src/librustrt/lib.rs +++ b/src/librustrt/lib.rs @@ -19,8 +19,14 @@ #![no_std] #![experimental] +#[cfg(stage0)] #[phase(syntax, link)] extern crate core; + +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate core; + extern crate alloc; extern crate libc; extern crate collections; @@ -28,7 +34,9 @@ extern crate collections; #[cfg(test)] extern crate realrustrt = "rustrt"; #[cfg(test)] extern crate test; #[cfg(test)] extern crate native; -#[cfg(test)] #[phase(syntax, link)] extern crate std; + +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std; pub use self::util::{Stdio, Stdout, Stderr}; pub use self::unwind::{begin_unwind, begin_unwind_fmt}; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 08348c96333..33d20ed7bcd 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -27,9 +27,15 @@ Core encoding and decoding interfaces. // test harness access #[cfg(test)] extern crate test; + +#[cfg(stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate log; + pub use self::serialize::{Decoder, Encoder, Decodable, Encodable, DecoderHelpers, EncoderHelpers}; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fbdbc13e1b4..85813c02d55 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -119,7 +119,8 @@ #[cfg(test)] extern crate native; #[cfg(test)] extern crate green; #[cfg(test)] extern crate debug; -#[cfg(test)] #[phase(syntax, link)] extern crate log; +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log; extern crate alloc; extern crate core; diff --git a/src/libsync/lib.rs b/src/libsync/lib.rs index fc4d5fec5f5..44d17e6fb95 100644 --- a/src/libsync/lib.rs +++ b/src/libsync/lib.rs @@ -25,9 +25,12 @@ #![deny(missing_doc)] -#[cfg(test)] +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(test, not(stage0))] +#[phase(plugin, link)] extern crate log; + extern crate alloc; pub use comm::{DuplexStream, duplex}; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 7fe67ad6f87..754518f5fea 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -32,8 +32,15 @@ This API is completely unstable and subject to change. extern crate serialize; extern crate term; + +#[cfg(stage0)] #[phase(syntax, link)] extern crate log; + +#[cfg(not(stage0))] +#[phase(plugin, link)] +extern crate log; + extern crate fmt_macros; extern crate debug; diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index cc813262576..76118f642ab 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -52,7 +52,8 @@ #![deny(missing_doc)] -#[phase(syntax, link)] extern crate log; +#[cfg(stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(not(stage0))] #[phase(plugin, link)] extern crate log; pub use terminfo::TerminfoTerminal; #[cfg(windows)] diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index f087b9289c3..f2af5943335 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -23,7 +23,9 @@ #![deny(deprecated_owned_vector)] #[cfg(test)] extern crate debug; -#[cfg(test)] #[phase(syntax, link)] extern crate log; + +#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log; +#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log; extern crate serialize; extern crate libc; -- cgit 1.4.1-3-g733a5