rollup merge of #22116: kmcallister/cfg_attr

Fixes #22070.
Fixes #19372.

r? @sfackler
This commit is contained in:
Alex Crichton 2015-02-10 08:43:01 -08:00
commit bbc8a54c63
10 changed files with 133 additions and 54 deletions

View File

@ -12,7 +12,7 @@ use attr::AttrMetaMethods;
use diagnostic::SpanHandler;
use fold::Folder;
use {ast, fold, attr};
use codemap::Spanned;
use codemap::{Spanned, respan};
use ptr::P;
use util::small_vector::SmallVector;
@ -26,6 +26,7 @@ struct Context<F> where F: FnMut(&[ast::Attribute]) -> bool {
// Support conditional compilation by transforming the AST, stripping out
// any items that do not belong in the current configuration
pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
let krate = process_cfg_attr(diagnostic, krate);
let config = krate.config.clone();
strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs))
}
@ -281,3 +282,49 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attr
attr::cfg_matches(diagnostic, cfg, &*mis[0])
})
}
struct CfgAttrFolder<'a> {
diag: &'a SpanHandler,
config: ast::CrateConfig,
}
// Process `#[cfg_attr]`.
fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
let mut fld = CfgAttrFolder {
diag: diagnostic,
config: krate.config.clone(),
};
fld.fold_crate(krate)
}
impl<'a> fold::Folder for CfgAttrFolder<'a> {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
if !attr.check_name("cfg_attr") {
return fold::noop_fold_attribute(attr, self);
}
let (cfg, mi) = match attr.meta_item_list() {
Some([ref cfg, ref mi]) => (cfg, mi),
_ => {
self.diag.span_err(attr.span, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
return None;
}
};
if attr::cfg_matches(self.diag, &self.config[], &cfg) {
Some(respan(mi.span, ast::Attribute_ {
id: attr::mk_attr_id(),
style: attr.node.style,
value: mi.clone(),
is_sugared_doc: false,
}))
} else {
None
}
}
// Need the ability to run pre-expansion.
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}

View File

@ -528,8 +528,6 @@ fn initial_syntax_expander_table(ecfg: &expand::ExpansionConfig) -> SyntaxEnv {
syntax_expanders.insert(intern("cfg"),
builtin_normal_expander(
ext::cfg::expand_cfg));
syntax_expanders.insert(intern("cfg_attr"),
Modifier(box ext::cfg_attr::expand));
syntax_expanders.insert(intern("trace_macros"),
builtin_normal_expander(
ext::trace_macros::expand_trace_macros));

View File

@ -1,34 +0,0 @@
// 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.
use ast;
use attr;
use codemap::Span;
use ext::base::ExtCtxt;
use ext::build::AstBuilder;
use ptr::P;
pub fn expand(cx: &mut ExtCtxt, sp: Span, mi: &ast::MetaItem, it: P<ast::Item>) -> P<ast::Item> {
let (cfg, attr) = match mi.node {
ast::MetaList(_, ref mis) if mis.len() == 2 => (&mis[0], &mis[1]),
_ => {
cx.span_err(sp, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
return it;
}
};
let mut out = (*it).clone();
if attr::cfg_matches(&cx.parse_sess.span_diagnostic, &cx.cfg, &**cfg) {
out.attrs.push(cx.attribute(attr.span, attr.clone()));
}
P(out)
}

View File

@ -844,7 +844,7 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
arm.guard.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
let rewritten_body = fld.fold_expr(rename_fld.fold_expr(arm.body));
ast::Arm {
attrs: arm.attrs.move_map(|x| fld.fold_attribute(x)),
attrs: fold::fold_attrs(arm.attrs, fld),
pats: rewritten_pats,
guard: rewritten_guard,
body: rewritten_body,
@ -1273,7 +1273,7 @@ fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<as
let (rewritten_fn_decl, rewritten_body)
= expand_and_rename_fn_decl_and_block(decl, body, fld);
SmallVector::one(P(ast::Method {
attrs: m.attrs.move_map(|a| fld.fold_attribute(a)),
attrs: fold::fold_attrs(m.attrs, fld),
id: id,
span: fld.new_span(m.span),
node: ast::MethDecl(fld.fold_ident(ident),

View File

@ -223,7 +223,7 @@ pub trait Folder : Sized {
noop_fold_lifetime_def(l, self)
}
fn fold_attribute(&mut self, at: Attribute) -> Attribute {
fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> {
noop_fold_attribute(at, self)
}
@ -373,9 +373,13 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
})
}
pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
attrs.into_iter().flat_map(|x| fld.fold_attribute(x).into_iter()).collect()
}
pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
Arm {
attrs: attrs.move_map(|x| fld.fold_attribute(x)),
attrs: fold_attrs(attrs, fld),
pats: pats.move_map(|x| fld.fold_pat(x)),
guard: guard.map(|x| fld.fold_expr(x)),
body: fld.fold_expr(body),
@ -475,7 +479,7 @@ pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
node: Variant_ {
id: fld.new_id(id),
name: name,
attrs: attrs.move_map(|x| fld.fold_attribute(x)),
attrs: fold_attrs(attrs, fld),
kind: match kind {
TupleVariantKind(variant_args) => {
TupleVariantKind(variant_args.move_map(|x|
@ -553,9 +557,9 @@ pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
})
}
pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Attribute {
pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> {
let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at;
Spanned {
Some(Spanned {
node: Attribute_ {
id: id,
style: style,
@ -563,7 +567,7 @@ pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Attribute {
is_sugared_doc: is_sugared_doc
},
span: fld.new_span(span)
}
})
}
pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_, fld: &mut T)
@ -845,8 +849,8 @@ pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
where T: Folder {
let new_id = folder.new_id(t.id);
let new_span = folder.new_span(t.span);
let new_attrs = t.attrs.iter().map(|attr| {
folder.fold_attribute((*attr).clone())
let new_attrs = t.attrs.iter().flat_map(|attr| {
folder.fold_attribute((*attr).clone()).into_iter()
}).collect();
let new_ident = folder.fold_ident(t.ident);
let new_type = folder.fold_ty(t.typ);
@ -866,7 +870,7 @@ pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
{
let new_attrs = at.attrs
.iter()
.map(|attr| folder.fold_attribute((*attr).clone()))
.flat_map(|attr| folder.fold_attribute((*attr).clone()).into_iter())
.collect();
let new_param = folder.fold_ty_param(at.ty_param);
ast::AssociatedType {
@ -909,7 +913,7 @@ pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructF
id: fld.new_id(id),
kind: kind,
ty: fld.fold_ty(ty),
attrs: attrs.move_map(|a| fld.fold_attribute(a))
attrs: fold_attrs(attrs, fld),
},
span: fld.new_span(span)
}
@ -1072,7 +1076,7 @@ pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMetho
TypeMethod {
id: fld.new_id(id),
ident: fld.fold_ident(ident),
attrs: attrs.move_map(|a| fld.fold_attribute(a)),
attrs: fold_attrs(attrs, fld),
unsafety: unsafety,
abi: abi,
decl: fld.fold_fn_decl(decl),
@ -1154,7 +1158,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
Item {
id: id,
ident: folder.fold_ident(ident),
attrs: attrs.move_map(|e| folder.fold_attribute(e)),
attrs: fold_attrs(attrs, folder),
node: node,
vis: vis,
span: folder.new_span(span)
@ -1165,7 +1169,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) ->
ni.map(|ForeignItem {id, ident, attrs, node, span, vis}| ForeignItem {
id: folder.new_id(id),
ident: folder.fold_ident(ident),
attrs: attrs.move_map(|x| folder.fold_attribute(x)),
attrs: fold_attrs(attrs, folder),
node: match node {
ForeignItemFn(fdec, generics) => {
ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics))
@ -1184,7 +1188,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) ->
pub fn noop_fold_method<T: Folder>(m: P<Method>, folder: &mut T) -> SmallVector<P<Method>> {
SmallVector::one(m.map(|Method {id, attrs, node, span}| Method {
id: folder.new_id(id),
attrs: attrs.move_map(|a| folder.fold_attribute(a)),
attrs: fold_attrs(attrs, folder),
node: match node {
MethDecl(ident,
generics,

View File

@ -96,7 +96,6 @@ pub mod ext {
pub mod base;
pub mod build;
pub mod cfg;
pub mod cfg_attr;
pub mod concat;
pub mod concat_idents;
pub mod deriving;

View File

@ -0,0 +1,18 @@
// Copyright 2015 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
// compile-flags: --cfg foo
// main is conditionally compiled, but the conditional compilation
// is conditional too!
#[cfg_attr(foo, cfg(bar))]
fn main() { }

View File

@ -0,0 +1,17 @@
// Copyright 2015 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 broken
// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
#![cfg_attr(broken, no_std)] //~ ERROR no_std is experimental
fn main() { }

View File

@ -0,0 +1,15 @@
// Copyright 2015 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.
// main is conditionally compiled, but the conditional compilation
// is conditional too!
#[cfg_attr(foo, cfg(bar))]
fn main() { }

View File

@ -0,0 +1,15 @@
// Copyright 2015 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.
// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044
#![cfg_attr(not_used, no_std)]
fn main() { }