Refactor CrateConfig
.
This commit is contained in:
parent
a2626410d7
commit
4b9b0d3474
8 changed files with 64 additions and 141 deletions
|
@ -25,7 +25,6 @@ use lint;
|
||||||
use middle::cstore;
|
use middle::cstore;
|
||||||
|
|
||||||
use syntax::ast::{self, IntTy, UintTy};
|
use syntax::ast::{self, IntTy, UintTy};
|
||||||
use syntax::attr;
|
|
||||||
use syntax::parse::{self, token};
|
use syntax::parse::{self, token};
|
||||||
use syntax::parse::token::InternedString;
|
use syntax::parse::token::InternedString;
|
||||||
use syntax::feature_gate::UnstableFeatures;
|
use syntax::feature_gate::UnstableFeatures;
|
||||||
|
@ -41,6 +40,7 @@ use std::collections::btree_map::Values as BTreeMapValuesIter;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
@ -945,47 +945,39 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
|
||||||
InternedString::new("unix")
|
InternedString::new("unix")
|
||||||
};
|
};
|
||||||
|
|
||||||
let mk = attr::mk_name_value_item_str;
|
let mut ret = HashSet::new();
|
||||||
let mut ret = vec![ // Target bindings.
|
// Target bindings.
|
||||||
mk(token::intern("target_os"), intern(os)),
|
ret.insert((token::intern("target_os"), Some(intern(os))));
|
||||||
mk(token::intern("target_family"), fam.clone()),
|
ret.insert((token::intern("target_family"), Some(fam.clone())));
|
||||||
mk(token::intern("target_arch"), intern(arch)),
|
ret.insert((token::intern("target_arch"), Some(intern(arch))));
|
||||||
mk(token::intern("target_endian"), intern(end)),
|
ret.insert((token::intern("target_endian"), Some(intern(end))));
|
||||||
mk(token::intern("target_pointer_width"), intern(wordsz)),
|
ret.insert((token::intern("target_pointer_width"), Some(intern(wordsz))));
|
||||||
mk(token::intern("target_env"), intern(env)),
|
ret.insert((token::intern("target_env"), Some(intern(env))));
|
||||||
mk(token::intern("target_vendor"), intern(vendor)),
|
ret.insert((token::intern("target_vendor"), Some(intern(vendor))));
|
||||||
];
|
if &fam == "windows" || &fam == "unix" {
|
||||||
match &fam[..] {
|
ret.insert((token::intern(&fam), None));
|
||||||
"windows" | "unix" => ret.push(attr::mk_word_item(token::intern(&fam))),
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
if sess.target.target.options.has_elf_tls {
|
if sess.target.target.options.has_elf_tls {
|
||||||
ret.push(attr::mk_word_item(token::intern("target_thread_local")));
|
ret.insert((token::intern("target_thread_local"), None));
|
||||||
}
|
}
|
||||||
for &i in &[8, 16, 32, 64, 128] {
|
for &i in &[8, 16, 32, 64, 128] {
|
||||||
if i <= max_atomic_width {
|
if i <= max_atomic_width {
|
||||||
let s = i.to_string();
|
let s = i.to_string();
|
||||||
ret.push(mk(token::intern("target_has_atomic"), intern(&s)));
|
ret.insert((token::intern("target_has_atomic"), Some(intern(&s))));
|
||||||
if &s == wordsz {
|
if &s == wordsz {
|
||||||
ret.push(mk(token::intern("target_has_atomic"), intern("ptr")));
|
ret.insert((token::intern("target_has_atomic"), Some(intern("ptr"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sess.opts.debug_assertions {
|
if sess.opts.debug_assertions {
|
||||||
ret.push(attr::mk_word_item(token::intern("debug_assertions")));
|
ret.insert((token::intern("debug_assertions"), None));
|
||||||
}
|
}
|
||||||
if sess.opts.crate_types.contains(&CrateTypeProcMacro) {
|
if sess.opts.crate_types.contains(&CrateTypeProcMacro) {
|
||||||
ret.push(attr::mk_word_item(token::intern("proc_macro")));
|
ret.insert((token::intern("proc_macro"), None));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_configuration(cfg: &mut ast::CrateConfig, name: ast::Name) {
|
|
||||||
if !cfg.iter().any(|mi| mi.name() == name) {
|
|
||||||
cfg.push(attr::mk_word_item(name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_configuration(sess: &Session,
|
pub fn build_configuration(sess: &Session,
|
||||||
mut user_cfg: ast::CrateConfig)
|
mut user_cfg: ast::CrateConfig)
|
||||||
-> ast::CrateConfig {
|
-> ast::CrateConfig {
|
||||||
|
@ -994,11 +986,10 @@ pub fn build_configuration(sess: &Session,
|
||||||
let default_cfg = default_configuration(sess);
|
let default_cfg = default_configuration(sess);
|
||||||
// If the user wants a test runner, then add the test cfg
|
// If the user wants a test runner, then add the test cfg
|
||||||
if sess.opts.test {
|
if sess.opts.test {
|
||||||
append_configuration(&mut user_cfg, token::intern("test"))
|
user_cfg.insert((token::intern("test"), None));
|
||||||
}
|
}
|
||||||
let mut v = user_cfg.into_iter().collect::<Vec<_>>();
|
user_cfg.extend(default_cfg.iter().cloned());
|
||||||
v.extend_from_slice(&default_cfg[..]);
|
user_cfg
|
||||||
v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
|
pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
|
||||||
|
@ -1244,11 +1235,14 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
|
||||||
let meta_item = panictry!(parser.parse_meta_item());
|
let meta_item = panictry!(parser.parse_meta_item());
|
||||||
|
|
||||||
if !parser.reader.is_eof() {
|
if !parser.reader.is_eof() {
|
||||||
early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}",
|
early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", s))
|
||||||
s))
|
} else if meta_item.is_meta_item_list() {
|
||||||
|
let msg =
|
||||||
|
format!("invalid predicate in --cfg command line argument: `{}`", meta_item.name());
|
||||||
|
early_error(ErrorOutputType::default(), &msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_item
|
(meta_item.name(), meta_item.value_str())
|
||||||
}).collect::<ast::CrateConfig>()
|
}).collect::<ast::CrateConfig>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,11 @@ use std::str;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use syntax::{ast, json};
|
use syntax::ast;
|
||||||
use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
|
use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
|
||||||
use syntax::feature_gate::{GatedCfg, UnstableFeatures};
|
use syntax::feature_gate::{GatedCfg, UnstableFeatures};
|
||||||
use syntax::parse::{self, PResult};
|
use syntax::parse::{self, PResult};
|
||||||
use syntax_pos::MultiSpan;
|
use syntax_pos::{DUMMY_SP, MultiSpan};
|
||||||
use errors::emitter::Emitter;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
@ -374,37 +373,11 @@ fn handle_explain(code: &str,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_cfg(cfg: &ast::CrateConfig,
|
|
||||||
output: ErrorOutputType) {
|
|
||||||
let emitter: Box<Emitter> = match output {
|
|
||||||
config::ErrorOutputType::HumanReadable(color_config) => {
|
|
||||||
Box::new(errors::emitter::EmitterWriter::stderr(color_config, None))
|
|
||||||
}
|
|
||||||
config::ErrorOutputType::Json => Box::new(json::JsonEmitter::basic()),
|
|
||||||
};
|
|
||||||
let handler = errors::Handler::with_emitter(true, false, emitter);
|
|
||||||
|
|
||||||
let mut saw_invalid_predicate = false;
|
|
||||||
for item in cfg.iter() {
|
|
||||||
if item.is_meta_item_list() {
|
|
||||||
saw_invalid_predicate = true;
|
|
||||||
handler.emit(&MultiSpan::new(),
|
|
||||||
&format!("invalid predicate in --cfg command line argument: `{}`",
|
|
||||||
item.name()),
|
|
||||||
errors::Level::Fatal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if saw_invalid_predicate {
|
|
||||||
panic!(errors::FatalError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||||
fn early_callback(&mut self,
|
fn early_callback(&mut self,
|
||||||
matches: &getopts::Matches,
|
matches: &getopts::Matches,
|
||||||
_: &config::Options,
|
_: &config::Options,
|
||||||
cfg: &ast::CrateConfig,
|
_: &ast::CrateConfig,
|
||||||
descriptions: &errors::registry::Registry,
|
descriptions: &errors::registry::Registry,
|
||||||
output: ErrorOutputType)
|
output: ErrorOutputType)
|
||||||
-> Compilation {
|
-> Compilation {
|
||||||
|
@ -413,7 +386,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||||
return Compilation::Stop;
|
return Compilation::Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_cfg(cfg, output);
|
|
||||||
Compilation::Continue
|
Compilation::Continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,24 +612,26 @@ impl RustcDefaultCalls {
|
||||||
let allow_unstable_cfg = UnstableFeatures::from_environment()
|
let allow_unstable_cfg = UnstableFeatures::from_environment()
|
||||||
.is_nightly_build();
|
.is_nightly_build();
|
||||||
|
|
||||||
for cfg in &sess.parse_sess.config {
|
let mut cfgs = Vec::new();
|
||||||
if !allow_unstable_cfg && GatedCfg::gate(cfg).is_some() {
|
for &(name, ref value) in sess.parse_sess.config.iter() {
|
||||||
|
let gated_cfg = GatedCfg::gate(&ast::MetaItem {
|
||||||
|
node: ast::MetaItemKind::Word(name),
|
||||||
|
span: DUMMY_SP,
|
||||||
|
});
|
||||||
|
if !allow_unstable_cfg && gated_cfg.is_some() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.is_word() {
|
cfgs.push(if let &Some(ref value) = value {
|
||||||
println!("{}", cfg.name());
|
format!("{}=\"{}\"", name, value)
|
||||||
} else if let Some(s) = cfg.value_str() {
|
|
||||||
println!("{}=\"{}\"", cfg.name(), s);
|
|
||||||
} else if cfg.is_meta_item_list() {
|
|
||||||
// Right now there are not and should not be any
|
|
||||||
// MetaItemKind::List items in the configuration returned by
|
|
||||||
// `build_configuration`.
|
|
||||||
panic!("Found an unexpected list in cfg attribute '{}'!", cfg.name())
|
|
||||||
} else {
|
} else {
|
||||||
// There also shouldn't be literals.
|
format!("{}", name)
|
||||||
panic!("Found an unexpected literal in cfg attribute '{}'!", cfg.name())
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfgs.sort();
|
||||||
|
for cfg in cfgs {
|
||||||
|
println!("{}", cfg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintRequest::TargetCPUs => {
|
PrintRequest::TargetCPUs => {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use syntax::{ast, attr};
|
use syntax::ast;
|
||||||
use llvm::LLVMRustHasFeature;
|
use llvm::LLVMRustHasFeature;
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc_trans::back::write::create_target_machine;
|
use rustc_trans::back::write::create_target_machine;
|
||||||
|
@ -44,7 +44,7 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
|
||||||
for feat in whitelist {
|
for feat in whitelist {
|
||||||
assert_eq!(feat.chars().last(), Some('\0'));
|
assert_eq!(feat.chars().last(), Some('\0'));
|
||||||
if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
|
if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
|
||||||
cfg.push(attr::mk_name_value_item_str(tf, intern(&feat[..feat.len() - 1])))
|
cfg.insert((tf, Some(intern(&feat[..feat.len() - 1]))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +73,6 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if crt_static {
|
if crt_static {
|
||||||
cfg.push(attr::mk_name_value_item_str(tf.clone(), intern("crt-static")));
|
cfg.insert((tf, Some(intern("crt-static"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||||
use syntax::ast::{self, Attribute, NestedMetaItem};
|
use syntax::ast::{self, Attribute, NestedMetaItem};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
||||||
use syntax::parse::token::InternedString;
|
use syntax::parse::token;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use ich::Fingerprint;
|
use ich::Fingerprint;
|
||||||
|
@ -88,12 +88,11 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
|
fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
|
||||||
for item in attr.meta_item_list().unwrap_or(&[]) {
|
for item in attr.meta_item_list().unwrap_or(&[]) {
|
||||||
if item.check_name(LABEL) {
|
if item.check_name(LABEL) {
|
||||||
let value = expect_associated_value(self.tcx, item);
|
let value = expect_associated_value(self.tcx, item);
|
||||||
match DepNode::from_label_string(&value[..], def_id) {
|
match DepNode::from_label_string(&value.as_str(), def_id) {
|
||||||
Ok(def_id) => return def_id,
|
Ok(def_id) => return def_id,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
self.tcx.sess.span_fatal(
|
self.tcx.sess.span_fatal(
|
||||||
|
@ -276,13 +275,7 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool {
|
||||||
if item.check_name(CFG) {
|
if item.check_name(CFG) {
|
||||||
let value = expect_associated_value(tcx, item);
|
let value = expect_associated_value(tcx, item);
|
||||||
debug!("check_config: searching for cfg {:?}", value);
|
debug!("check_config: searching for cfg {:?}", value);
|
||||||
for cfg in &config[..] {
|
return config.contains(&(value, None));
|
||||||
if cfg.check_name(&value[..]) {
|
|
||||||
debug!("check_config: matched {:?}", cfg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,9 +284,9 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool {
|
||||||
&format!("no cfg attribute"));
|
&format!("no cfg attribute"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> InternedString {
|
fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name {
|
||||||
if let Some(value) = item.value_str() {
|
if let Some(value) = item.value_str() {
|
||||||
value
|
token::intern(&value)
|
||||||
} else {
|
} else {
|
||||||
let msg = if let Some(name) = item.name() {
|
let msg = if let Some(name) = item.name() {
|
||||||
format!("associated value expected for `{}`", name)
|
format!("associated value expected for `{}`", name)
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
use rustc::ty::TyCtxt;
|
use rustc::ty::TyCtxt;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::parse::token::InternedString;
|
use syntax::parse::token;
|
||||||
|
|
||||||
use {ModuleSource, ModuleTranslation};
|
use {ModuleSource, ModuleTranslation};
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mname = self.field(attr, MODULE);
|
let mname = self.field(attr, MODULE);
|
||||||
let mtrans = self.modules.iter().find(|mtrans| &mtrans.name[..] == &mname[..]);
|
let mtrans = self.modules.iter().find(|mtrans| *mtrans.name == *mname.as_str());
|
||||||
let mtrans = match mtrans {
|
let mtrans = match mtrans {
|
||||||
Some(m) => m,
|
Some(m) => m,
|
||||||
None => {
|
None => {
|
||||||
|
@ -113,11 +113,11 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field(&self, attr: &ast::Attribute, name: &str) -> InternedString {
|
fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name {
|
||||||
for item in attr.meta_item_list().unwrap_or(&[]) {
|
for item in attr.meta_item_list().unwrap_or(&[]) {
|
||||||
if item.check_name(name) {
|
if item.check_name(name) {
|
||||||
if let Some(value) = item.value_str() {
|
if let Some(value) = item.value_str() {
|
||||||
return value;
|
return token::intern(&value);
|
||||||
} else {
|
} else {
|
||||||
self.tcx.sess.span_fatal(
|
self.tcx.sess.span_fatal(
|
||||||
item.span,
|
item.span,
|
||||||
|
@ -137,7 +137,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
|
||||||
let config = &self.tcx.sess.parse_sess.config;
|
let config = &self.tcx.sess.parse_sess.config;
|
||||||
let value = self.field(attr, CFG);
|
let value = self.field(attr, CFG);
|
||||||
debug!("check_config(config={:?}, value={:?})", config, value);
|
debug!("check_config(config={:?}, value={:?})", config, value);
|
||||||
if config.iter().any(|c| c.check_name(&value[..])) {
|
if config.iter().any(|&(name, _)| name == value) {
|
||||||
debug!("check_config: matched");
|
debug!("check_config: matched");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ use print::pprust;
|
||||||
use ptr::P;
|
use ptr::P;
|
||||||
use tokenstream::{TokenTree};
|
use tokenstream::{TokenTree};
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
@ -485,7 +486,7 @@ pub struct WhereEqPredicate {
|
||||||
|
|
||||||
/// The set of MetaItems that define the compilation environment of the crate,
|
/// The set of MetaItems that define the compilation environment of the crate,
|
||||||
/// used to drive conditional compilation
|
/// used to drive conditional compilation
|
||||||
pub type CrateConfig = Vec<P<MetaItem>>;
|
pub type CrateConfig = HashSet<(Name, Option<InternedString>)>;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub struct Crate {
|
pub struct Crate {
|
||||||
|
@ -519,7 +520,7 @@ pub type MetaItem = Spanned<MetaItemKind>;
|
||||||
/// A compile-time attribute item.
|
/// A compile-time attribute item.
|
||||||
///
|
///
|
||||||
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
|
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
|
||||||
#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum MetaItemKind {
|
pub enum MetaItemKind {
|
||||||
/// Word meta item.
|
/// Word meta item.
|
||||||
///
|
///
|
||||||
|
@ -535,34 +536,6 @@ pub enum MetaItemKind {
|
||||||
NameValue(Name, Lit),
|
NameValue(Name, Lit),
|
||||||
}
|
}
|
||||||
|
|
||||||
// can't be derived because the MetaItemKind::List requires an unordered comparison
|
|
||||||
impl PartialEq for MetaItemKind {
|
|
||||||
fn eq(&self, other: &MetaItemKind) -> bool {
|
|
||||||
use self::MetaItemKind::*;
|
|
||||||
match *self {
|
|
||||||
Word(ref ns) => match *other {
|
|
||||||
Word(ref no) => (*ns) == (*no),
|
|
||||||
_ => false
|
|
||||||
},
|
|
||||||
List(ref ns, ref miss) => match *other {
|
|
||||||
List(ref no, ref miso) => {
|
|
||||||
ns == no &&
|
|
||||||
miss.iter().all(|mi| {
|
|
||||||
miso.iter().any(|x| x.node == mi.node)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => false
|
|
||||||
},
|
|
||||||
NameValue(ref ns, ref vs) => match *other {
|
|
||||||
NameValue(ref no, ref vo) => {
|
|
||||||
(*ns) == (*no) && vs.node == vo.node
|
|
||||||
}
|
|
||||||
_ => false
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A Block (`{ .. }`).
|
/// A Block (`{ .. }`).
|
||||||
///
|
///
|
||||||
/// E.g. `{ .. }` as in `fn foo() { .. }`
|
/// E.g. `{ .. }` as in `fn foo() { .. }`
|
||||||
|
|
|
@ -400,18 +400,6 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos, hi: By
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Searching */
|
|
||||||
/// Check if `needle` occurs in `haystack` by a structural
|
|
||||||
/// comparison. This is slightly subtle, and relies on ignoring the
|
|
||||||
/// span included in the `==` comparison a plain MetaItem.
|
|
||||||
pub fn contains(haystack: &[P<MetaItem>], needle: &MetaItem) -> bool {
|
|
||||||
debug!("attr::contains (name={})", needle.name());
|
|
||||||
haystack.iter().any(|item| {
|
|
||||||
debug!(" testing: {}", item.name());
|
|
||||||
item.node == needle.node
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool {
|
pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool {
|
||||||
debug!("attr::list_contains_name (name={})", name);
|
debug!("attr::list_contains_name (name={})", name);
|
||||||
items.iter().any(|item| {
|
items.iter().any(|item| {
|
||||||
|
@ -558,7 +546,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
|
||||||
if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
|
if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
|
||||||
gated_cfg.check_and_emit(sess, feats);
|
gated_cfg.check_and_emit(sess, feats);
|
||||||
}
|
}
|
||||||
contains(&sess.config, cfg)
|
sess.config.contains(&(cfg.name(), cfg.value_str()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ use str::char_at;
|
||||||
use tokenstream;
|
use tokenstream;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -64,7 +65,7 @@ impl ParseSess {
|
||||||
ParseSess {
|
ParseSess {
|
||||||
span_diagnostic: handler,
|
span_diagnostic: handler,
|
||||||
unstable_features: UnstableFeatures::from_environment(),
|
unstable_features: UnstableFeatures::from_environment(),
|
||||||
config: Vec::new(),
|
config: HashSet::new(),
|
||||||
included_mod_stack: RefCell::new(vec![]),
|
included_mod_stack: RefCell::new(vec![]),
|
||||||
code_map: code_map
|
code_map: code_map
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue