From 9519abecfb727d71bd8209ffd94816b2cb87180f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 24 Sep 2014 20:22:57 -0700 Subject: [PATCH] Convert cfg syntax to new system This removes the ability to use `foo(bar)` style cfgs. Switch them to `foo_bar` or `foo="bar"` instead. [breaking-change] --- src/librustc/driver/driver.rs | 4 +- src/libsyntax/attr.rs | 26 +++++++++++++ src/libsyntax/config.rs | 37 +++++++++++++++++-- src/libsyntax/ext/cfg.rs | 19 ++++++---- src/libsyntax/ext/cfg_attr.rs | 25 +------------ src/test/compile-fail/asm-in-bad-modifier.rs | 9 ++--- src/test/compile-fail/asm-misplaced-option.rs | 4 +- src/test/compile-fail/asm-out-assign-imm.rs | 8 ++-- src/test/compile-fail/asm-out-no-modifier.rs | 8 ++-- src/test/compile-fail/asm-out-read-uninit.rs | 8 ++-- src/test/compile-fail/test-cfg.rs | 2 +- src/test/pretty/raw-str-nonexpr.rs | 2 +- src/test/run-pass/syntax-extension-cfg.rs | 16 ++++---- 13 files changed, 102 insertions(+), 66 deletions(-) diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 4ff9133c8a5..ed0aeb952a1 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -226,7 +226,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // baz! should not use this definition unless foo is enabled. krate = time(time_passes, "configuration 1", krate, |krate| - syntax::config::strip_unconfigured_items(krate)); + syntax::config::strip_unconfigured_items(sess.diagnostic(), krate)); let mut addl_plugins = Some(addl_plugins); let Plugins { macros, registrars } @@ -307,7 +307,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, // strip again, in case expansion added anything with a #[cfg]. krate = time(time_passes, "configuration 2", krate, |krate| - syntax::config::strip_unconfigured_items(krate)); + syntax::config::strip_unconfigured_items(sess.diagnostic(), krate)); krate = time(time_passes, "maybe building test harness", krate, |krate| syntax::test::modify_for_testing(&sess.parse_sess, diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index ace1e1245c7..efc75de7142 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -307,6 +307,32 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool { } } +/// Tests if a cfg-pattern matches the cfg set +pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P], cfg: &ast::MetaItem) -> bool { + match cfg.node { + ast::MetaList(ref pred, ref mis) if pred.get() == "any" => + mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi)), + ast::MetaList(ref pred, ref mis) if pred.get() == "all" => + mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi)), + ast::MetaList(ref pred, ref mis) if pred.get() == "not" => { + // NOTE: turn on after snapshot + /* + if mis.len() != 1 { + diagnostic.span_warn(cfg.span, "the use of multiple cfgs in the same `not` \ + statement is deprecated. Change `not(a, b)` to \ + `not(all(a, b))`."); + } + */ + !mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi)) + } + ast::MetaList(ref pred, _) => { + diagnostic.span_err(cfg.span, format!("invalid predicate `{}`", pred).as_slice()); + false + }, + ast::MetaWord(_) | ast::MetaNameValue(..) => contains(cfgs, cfg), + } +} + /// Tests if any `cfg(...)` meta items in `metas` match `cfg`. e.g. /// /// test_cfg(`[foo="a", bar]`, `[cfg(foo), cfg(bar)]`) == true diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 3b250de8701..5b17f6f004a 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attr::AttrMetaMethods; +use diagnostic::SpanHandler; use fold::Folder; use {ast, fold, attr}; use codemap::Spanned; @@ -21,9 +23,9 @@ struct Context<'a> { // Support conditional compilation by transforming the AST, stripping out // any items that do not belong in the current configuration -pub fn strip_unconfigured_items(krate: ast::Crate) -> ast::Crate { +pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate { let config = krate.config.clone(); - strip_items(krate, |attrs| in_cfg(config.as_slice(), attrs)) + strip_items(krate, |attrs| in_cfg(diagnostic, config.as_slice(), attrs)) } impl<'a> fold::Folder for Context<'a> { @@ -249,7 +251,34 @@ fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool { // Determine if an item should be translated in the current crate // configuration based on the item's attributes -fn in_cfg(cfg: &[P], attrs: &[ast::Attribute]) -> bool { - attr::test_cfg(cfg, attrs.iter()) +fn in_cfg(diagnostic: &SpanHandler, cfg: &[P], attrs: &[ast::Attribute]) -> bool { + let mut in_cfg = false; + let mut seen_cfg = false; + for attr in attrs.iter() { + let mis = match attr.node.value.node { + ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis, + _ => continue + }; + + // NOTE: turn on after snapshot + /* + if mis.len() != 1 { + diagnostic.span_warn(attr.span, "The use of multiple cfgs in the top level of \ + `#[cfg(..)]` is deprecated. Change `#[cfg(a, b)]` to \ + `#[cfg(all(a, b))]`."); + } + + if seen_cfg { + diagnostic.span_warn(attr.span, "The semantics of multiple `#[cfg(..)]` attributes on \ + same item are changing from the union of the cfgs to \ + the intersection of the cfgs. Change `#[cfg(a)] \ + #[cfg(b)]` to `#[cfg(any(a, b))]`."); + } + */ + + seen_cfg = true; + in_cfg |= mis.iter().all(|mi| attr::cfg_matches(diagnostic, cfg, &**mi)); + } + in_cfg | !seen_cfg } diff --git a/src/libsyntax/ext/cfg.rs b/src/libsyntax/ext/cfg.rs index 79cb47fee7b..342e7e6d52e 100644 --- a/src/libsyntax/ext/cfg.rs +++ b/src/libsyntax/ext/cfg.rs @@ -22,7 +22,6 @@ use ext::build::AstBuilder; use attr; use attr::*; use parse::attr::ParserAttr; -use parse::token::InternedString; use parse::token; @@ -39,11 +38,17 @@ pub fn expand_cfg<'cx>(cx: &mut ExtCtxt, p.expect(&token::COMMA); } - // test_cfg searches for meta items looking like `cfg(foo, ...)` - let in_cfg = Some(cx.meta_list(sp, InternedString::new("cfg"), cfgs)); + // NOTE: turn on after snapshot + /* + if cfgs.len() != 1 { + cx.span_warn(sp, "The use of multiple cfgs at the top level of `cfg!` \ + is deprecated. Change `cfg!(a, b)` to \ + `cfg!(all(a, b))`."); + } + */ - let matches_cfg = attr::test_cfg(cx.cfg().as_slice(), - in_cfg.iter()); - let e = cx.expr_bool(sp, matches_cfg); - MacExpr::new(e) + let matches_cfg = cfgs.iter().all(|cfg| attr::cfg_matches(&cx.parse_sess.span_diagnostic, + cx.cfg.as_slice(), &**cfg)); + + MacExpr::new(cx.expr_bool(sp, matches_cfg)) } diff --git a/src/libsyntax/ext/cfg_attr.rs b/src/libsyntax/ext/cfg_attr.rs index ad02b50f248..a85f12edb22 100644 --- a/src/libsyntax/ext/cfg_attr.rs +++ b/src/libsyntax/ext/cfg_attr.rs @@ -25,33 +25,10 @@ pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P) }; let mut out = (*it).clone(); - if cfg_matches(cx, &**cfg) { + if attr::cfg_matches(&cx.parse_sess.span_diagnostic, cx.cfg.as_slice(), &**cfg) { out.attrs.push(cx.attribute(attr.span, attr.clone())); } P(out) } -fn cfg_matches(cx: &mut ExtCtxt, cfg: &ast::MetaItem) -> bool { - match cfg.node { - ast::MetaList(ref pred, ref mis) if pred.get() == "any" => - mis.iter().any(|mi| cfg_matches(cx, &**mi)), - ast::MetaList(ref pred, ref mis) if pred.get() == "all" => - mis.iter().all(|mi| cfg_matches(cx, &**mi)), - ast::MetaList(ref pred, ref mis) if pred.get() == "not" => { - if mis.len() != 1 { - cx.span_err(cfg.span, format!("expected 1 value, got {}", - mis.len()).as_slice()); - return false; - } - !cfg_matches(cx, &*mis[0]) - } - ast::MetaList(ref pred, _) => { - cx.span_err(cfg.span, - format!("invalid predicate `{}`", pred).as_slice()); - false - }, - ast::MetaWord(_) | ast::MetaNameValue(..) => - attr::contains(cx.cfg.as_slice(), cfg), - } -} diff --git a/src/test/compile-fail/asm-in-bad-modifier.rs b/src/test/compile-fail/asm-in-bad-modifier.rs index 82ecfd0ca72..d2216d95867 100644 --- a/src/test/compile-fail/asm-in-bad-modifier.rs +++ b/src/test/compile-fail/asm-in-bad-modifier.rs @@ -12,10 +12,9 @@ fn foo(x: int) { println!("{}", x); } -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "x86_64")] -#[cfg(target_arch = "arm")] - +#[cfg(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm"))] pub fn main() { let x: int; let y: int; @@ -27,5 +26,5 @@ pub fn main() { foo(y); } -#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))] +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))] pub fn main() {} diff --git a/src/test/compile-fail/asm-misplaced-option.rs b/src/test/compile-fail/asm-misplaced-option.rs index 8e93b91276f..8006789d440 100644 --- a/src/test/compile-fail/asm-misplaced-option.rs +++ b/src/test/compile-fail/asm-misplaced-option.rs @@ -14,8 +14,8 @@ #![allow(dead_code)] -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86", + target_arch = "x86_64"))] pub fn main() { // assignment not dead let mut x: int = 0; diff --git a/src/test/compile-fail/asm-out-assign-imm.rs b/src/test/compile-fail/asm-out-assign-imm.rs index 2319594cb97..a35f72ab4dc 100644 --- a/src/test/compile-fail/asm-out-assign-imm.rs +++ b/src/test/compile-fail/asm-out-assign-imm.rs @@ -12,9 +12,9 @@ fn foo(x: int) { println!("{}", x); } -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "x86_64")] -#[cfg(target_arch = "arm")] +#[cfg(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm"))] pub fn main() { let x: int; x = 1; //~ NOTE prior assignment occurs here @@ -25,5 +25,5 @@ pub fn main() { foo(x); } -#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))] +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))] pub fn main() {} diff --git a/src/test/compile-fail/asm-out-no-modifier.rs b/src/test/compile-fail/asm-out-no-modifier.rs index 5535c167e3c..76d4c516c4e 100644 --- a/src/test/compile-fail/asm-out-no-modifier.rs +++ b/src/test/compile-fail/asm-out-no-modifier.rs @@ -12,9 +12,9 @@ fn foo(x: int) { println!("{}", x); } -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "x86_64")] -#[cfg(target_arch = "arm")] +#[cfg(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm"))] pub fn main() { let x: int; unsafe { @@ -23,5 +23,5 @@ pub fn main() { foo(x); } -#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))] +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))] pub fn main() {} diff --git a/src/test/compile-fail/asm-out-read-uninit.rs b/src/test/compile-fail/asm-out-read-uninit.rs index 1d807acefe6..aa83a89fec0 100644 --- a/src/test/compile-fail/asm-out-read-uninit.rs +++ b/src/test/compile-fail/asm-out-read-uninit.rs @@ -12,9 +12,9 @@ fn foo(x: int) { println!("{}", x); } -#[cfg(target_arch = "x86")] -#[cfg(target_arch = "x86_64")] -#[cfg(target_arch = "arm")] +#[cfg(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm"))] pub fn main() { let x: int; unsafe { @@ -23,5 +23,5 @@ pub fn main() { foo(x); } -#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"), not(target_arch = "arm"))] +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))] pub fn main() {} diff --git a/src/test/compile-fail/test-cfg.rs b/src/test/compile-fail/test-cfg.rs index a8c52813513..8be1c35ae5c 100644 --- a/src/test/compile-fail/test-cfg.rs +++ b/src/test/compile-fail/test-cfg.rs @@ -10,7 +10,7 @@ // compile-flags: --cfg foo -#[cfg(foo, bar)] // foo AND bar +#[cfg(all(foo, bar))] // foo AND bar fn foo() {} fn main() { diff --git a/src/test/pretty/raw-str-nonexpr.rs b/src/test/pretty/raw-str-nonexpr.rs index 08d599b1e6f..965b1760f1f 100644 --- a/src/test/pretty/raw-str-nonexpr.rs +++ b/src/test/pretty/raw-str-nonexpr.rs @@ -12,7 +12,7 @@ #![feature(asm)] -#[cfg = r#"just parse this"#] +#[cfg(foo = r#"just parse this"#)] extern crate r##"blah"## as blah; fn main() { unsafe { asm!(r###"blah"###); } } diff --git a/src/test/run-pass/syntax-extension-cfg.rs b/src/test/run-pass/syntax-extension-cfg.rs index d09a4d990fd..ab6468b2a85 100644 --- a/src/test/run-pass/syntax-extension-cfg.rs +++ b/src/test/run-pass/syntax-extension-cfg.rs @@ -8,27 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: --cfg foo --cfg bar(baz) --cfg qux="foo" +// compile-flags: --cfg foo --cfg qux="foo" pub fn main() { // check if ! cfg!(foo) { fail!() } if cfg!(not(foo)) { fail!() } - if ! cfg!(bar(baz)) { fail!() } - if cfg!(not(bar(baz))) { fail!() } - if ! cfg!(qux="foo") { fail!() } if cfg!(not(qux="foo")) { fail!() } - if ! cfg!(foo, bar(baz), qux="foo") { fail!() } - if cfg!(not(foo, bar(baz), qux="foo")) { fail!() } + if ! cfg!(foo, qux="foo") { fail!() } + if cfg!(not(foo, qux="foo")) { fail!() } + if cfg!(all(not(foo, qux="foo"))) { fail!() } if cfg!(not_a_cfg) { fail!() } - if cfg!(not_a_cfg, foo, bar(baz), qux="foo") { fail!() } + if cfg!(not_a_cfg, foo, qux="foo") { fail!() } + if cfg!(all(not_a_cfg, foo, qux="foo")) { fail!() } + if ! cfg!(any(not_a_cfg, foo)) { fail!() } if ! cfg!(not(not_a_cfg)) { fail!() } - if ! cfg!(not(not_a_cfg), foo, bar(baz), qux="foo") { fail!() } + if ! cfg!(not(not_a_cfg), foo, qux="foo") { fail!() } if cfg!(trailing_comma, ) { fail!() } }