rustc: Process #[cfg]/#[cfg_attr] on crates
This commit implements processing these two attributes at the crate level as well as at the item level. When #[cfg] is applied at the crate level, then the entire crate will be omitted if the cfg doesn't match. The #[cfg_attr] attribute is processed as usual in that the attribute is included or not depending on whether the cfg matches. This was spurred on by motivations of #18585 where #[cfg_attr] annotations will be applied at the crate-level. cc #18585
This commit is contained in:
parent
45cbdec417
commit
3dbd32854f
11 changed files with 127 additions and 23 deletions
|
@ -212,11 +212,6 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||||
*ty == config::CrateTypeExecutable
|
*ty == config::CrateTypeExecutable
|
||||||
});
|
});
|
||||||
|
|
||||||
krate = time(time_passes, "crate injection", krate, |krate|
|
|
||||||
syntax::std_inject::maybe_inject_crates_ref(krate,
|
|
||||||
sess.opts.alt_std_name.clone(),
|
|
||||||
any_exe));
|
|
||||||
|
|
||||||
// strip before expansion to allow macros to depend on
|
// strip before expansion to allow macros to depend on
|
||||||
// configuration variables e.g/ in
|
// configuration variables e.g/ in
|
||||||
//
|
//
|
||||||
|
@ -228,6 +223,11 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||||
krate = time(time_passes, "configuration 1", krate, |krate|
|
krate = time(time_passes, "configuration 1", krate, |krate|
|
||||||
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
|
syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
|
||||||
|
|
||||||
|
krate = time(time_passes, "crate injection", krate, |krate|
|
||||||
|
syntax::std_inject::maybe_inject_crates_ref(krate,
|
||||||
|
sess.opts.alt_std_name.clone(),
|
||||||
|
any_exe));
|
||||||
|
|
||||||
let mut addl_plugins = Some(addl_plugins);
|
let mut addl_plugins = Some(addl_plugins);
|
||||||
let Plugins { macros, registrars }
|
let Plugins { macros, registrars }
|
||||||
= time(time_passes, "plugin loading", (), |_|
|
= time(time_passes, "plugin loading", (), |_|
|
||||||
|
|
|
@ -15,6 +15,8 @@ use {ast, fold, attr};
|
||||||
use codemap::Spanned;
|
use codemap::Spanned;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
|
|
||||||
|
use util::small_vector::SmallVector;
|
||||||
|
|
||||||
/// A folder that strips out items that do not belong in the current
|
/// A folder that strips out items that do not belong in the current
|
||||||
/// configuration.
|
/// configuration.
|
||||||
struct Context<'a> {
|
struct Context<'a> {
|
||||||
|
@ -47,6 +49,9 @@ impl<'a> fold::Folder for Context<'a> {
|
||||||
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
||||||
fold::noop_fold_mac(mac, self)
|
fold::noop_fold_mac(mac, self)
|
||||||
}
|
}
|
||||||
|
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
||||||
|
fold_item(self, item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn strip_items(krate: ast::Crate,
|
pub fn strip_items(krate: ast::Crate,
|
||||||
|
@ -72,13 +77,9 @@ fn fold_mod(cx: &mut Context, ast::Mod {inner, view_items, items}: ast::Mod) ->
|
||||||
view_items: view_items.into_iter().filter_map(|a| {
|
view_items: view_items.into_iter().filter_map(|a| {
|
||||||
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
|
filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
|
||||||
}).collect(),
|
}).collect(),
|
||||||
items: items.into_iter().filter_map(|a| {
|
items: items.into_iter().flat_map(|a| {
|
||||||
if item_in_cfg(cx, &*a) {
|
cx.fold_item(a).into_iter()
|
||||||
Some(cx.fold_item(a))
|
}).collect()
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}).flat_map(|x| x.into_iter()).collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +105,14 @@ fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_item(cx: &mut Context, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
||||||
|
if item_in_cfg(cx, &*item) {
|
||||||
|
SmallVector::one(item.map(|i| cx.fold_item_simple(i)))
|
||||||
|
} else {
|
||||||
|
SmallVector::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ {
|
fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ {
|
||||||
let item = match item {
|
let item = match item {
|
||||||
ast::ItemImpl(a, b, c, impl_items) => {
|
ast::ItemImpl(a, b, c, impl_items) => {
|
||||||
|
|
|
@ -1057,12 +1057,41 @@ pub fn noop_fold_mod<T: Folder>(Mod {inner, view_items, items}: Mod, folder: &mu
|
||||||
|
|
||||||
pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, exported_macros, span}: Crate,
|
pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, exported_macros, span}: Crate,
|
||||||
folder: &mut T) -> Crate {
|
folder: &mut T) -> Crate {
|
||||||
|
let config = folder.fold_meta_items(config);
|
||||||
|
|
||||||
|
let mut items = folder.fold_item(P(ast::Item {
|
||||||
|
ident: token::special_idents::invalid,
|
||||||
|
attrs: attrs,
|
||||||
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
vis: ast::Public,
|
||||||
|
span: span,
|
||||||
|
node: ast::ItemMod(module),
|
||||||
|
})).into_iter();
|
||||||
|
|
||||||
|
let (module, attrs, span) = match items.next() {
|
||||||
|
Some(item) => {
|
||||||
|
assert!(items.next().is_none(),
|
||||||
|
"a crate cannot expand to more than one item");
|
||||||
|
item.and_then(|ast::Item { attrs, span, node, .. }| {
|
||||||
|
match node {
|
||||||
|
ast::ItemMod(m) => (m, attrs, span),
|
||||||
|
_ => panic!("fold converted a module to not a module"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => (ast::Mod {
|
||||||
|
inner: span,
|
||||||
|
view_items: Vec::new(),
|
||||||
|
items: Vec::new(),
|
||||||
|
}, Vec::new(), span)
|
||||||
|
};
|
||||||
|
|
||||||
Crate {
|
Crate {
|
||||||
module: folder.fold_mod(module),
|
module: module,
|
||||||
attrs: attrs.move_map(|x| folder.fold_attribute(x)),
|
attrs: attrs,
|
||||||
config: folder.fold_meta_items(config),
|
config: config,
|
||||||
exported_macros: exported_macros,
|
exported_macros: exported_macros,
|
||||||
span: folder.new_span(span)
|
span: span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,10 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
||||||
self.cx.path.push(i.ident);
|
let ident = i.ident;
|
||||||
|
if ident.name != token::special_idents::invalid.name {
|
||||||
|
self.cx.path.push(ident);
|
||||||
|
}
|
||||||
debug!("current path: {}",
|
debug!("current path: {}",
|
||||||
ast_util::path_name_i(self.cx.path.as_slice()));
|
ast_util::path_name_i(self.cx.path.as_slice()));
|
||||||
|
|
||||||
|
@ -143,7 +146,9 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
|
||||||
ast::ItemMod(..) => fold::noop_fold_item(i, self),
|
ast::ItemMod(..) => fold::noop_fold_item(i, self),
|
||||||
_ => SmallVector::one(i),
|
_ => SmallVector::one(i),
|
||||||
};
|
};
|
||||||
self.cx.path.pop();
|
if ident.name != token::special_idents::invalid.name {
|
||||||
|
self.cx.path.pop();
|
||||||
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
src/test/auxiliary/stability_cfg1.rs
Normal file
12
src/test/auxiliary/stability_cfg1.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
#![cfg_attr(foo, experimental)]
|
||||||
|
#![cfg_attr(not(foo), stable)]
|
15
src/test/auxiliary/stability_cfg2.rs
Normal file
15
src/test/auxiliary/stability_cfg2.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// compile-flags:--cfg foo
|
||||||
|
|
||||||
|
#![cfg_attr(foo, experimental)]
|
||||||
|
#![cfg_attr(not(foo), stable)]
|
||||||
|
|
13
src/test/compile-fail/cfg-in-crate-1.rs
Normal file
13
src/test/compile-fail/cfg-in-crate-1.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// error-pattern:main function not found
|
||||||
|
|
||||||
|
#![cfg(bar)]
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
// aux-build:lint_stability.rs
|
// aux-build:lint_stability.rs
|
||||||
// aux-build:inherited_stability.rs
|
// aux-build:inherited_stability.rs
|
||||||
|
// aux-build:stability_cfg1.rs
|
||||||
|
// aux-build:stability_cfg2.rs
|
||||||
|
|
||||||
#![feature(globs, phase)]
|
#![feature(globs, phase)]
|
||||||
#![deny(unstable)]
|
#![deny(unstable)]
|
||||||
|
@ -18,6 +20,9 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
mod cross_crate {
|
mod cross_crate {
|
||||||
|
extern crate stability_cfg1;
|
||||||
|
extern crate stability_cfg2; //~ ERROR: use of experimental item
|
||||||
|
|
||||||
#[phase(plugin, link)]
|
#[phase(plugin, link)]
|
||||||
extern crate lint_stability; //~ ERROR: use of unmarked item
|
extern crate lint_stability; //~ ERROR: use of unmarked item
|
||||||
use self::lint_stability::*;
|
use self::lint_stability::*;
|
||||||
|
|
|
@ -2,10 +2,10 @@ digraph block {
|
||||||
N0[label="entry"];
|
N0[label="entry"];
|
||||||
N1[label="exit"];
|
N1[label="exit"];
|
||||||
N2[label="expr 3i"];
|
N2[label="expr 3i"];
|
||||||
N3[label="expr 33i"];
|
N3[label="expr 4"];
|
||||||
N4[label="expr 3i + 33i"];
|
N4[label="expr 3i + 4"];
|
||||||
N5[label="stmt 3i + 33i;"];
|
N5[label="stmt 3i + 4;"];
|
||||||
N6[label="block { 3i + 33i; }"];
|
N6[label="block { 3i + 4; }"];
|
||||||
N0 -> N2;
|
N0 -> N2;
|
||||||
N2 -> N3;
|
N2 -> N3;
|
||||||
N3 -> N4;
|
N3 -> N4;
|
||||||
|
|
|
@ -9,5 +9,5 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
pub fn expr_add_3() {
|
pub fn expr_add_3() {
|
||||||
3i + 33i;
|
3i + 4;
|
||||||
}
|
}
|
||||||
|
|
16
src/test/run-pass/cfg-in-crate-1.rs
Normal file
16
src/test/run-pass/cfg-in-crate-1.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// compile-flags: --cfg bar -D warnings
|
||||||
|
// ignore-pretty
|
||||||
|
|
||||||
|
#![cfg(bar)]
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in a new issue