about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/session/config.rs58
-rw-r--r--src/librustc_driver/lib.rs64
-rw-r--r--src/librustc_driver/target_features.rs6
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs17
-rw-r--r--src/librustc_trans/assert_module_sources.rs10
-rw-r--r--src/libsyntax/ast.rs33
-rw-r--r--src/libsyntax/attr.rs14
-rw-r--r--src/libsyntax/parse/mod.rs3
8 files changed, 64 insertions, 141 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 1502811baee..d22d5d915f6 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -25,7 +25,6 @@ use lint;
 use middle::cstore;
 
 use syntax::ast::{self, IntTy, UintTy};
-use syntax::attr;
 use syntax::parse::{self, token};
 use syntax::parse::token::InternedString;
 use syntax::feature_gate::UnstableFeatures;
@@ -41,6 +40,7 @@ use std::collections::btree_map::Values as BTreeMapValuesIter;
 use std::fmt;
 use std::hash::Hasher;
 use std::collections::hash_map::DefaultHasher;
+use std::collections::HashSet;
 use std::iter::FromIterator;
 use std::path::PathBuf;
 
@@ -945,47 +945,39 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
         InternedString::new("unix")
     };
 
-    let mk = attr::mk_name_value_item_str;
-    let mut ret = vec![ // Target bindings.
-        mk(token::intern("target_os"), intern(os)),
-        mk(token::intern("target_family"), fam.clone()),
-        mk(token::intern("target_arch"), intern(arch)),
-        mk(token::intern("target_endian"), intern(end)),
-        mk(token::intern("target_pointer_width"), intern(wordsz)),
-        mk(token::intern("target_env"), intern(env)),
-        mk(token::intern("target_vendor"), intern(vendor)),
-    ];
-    match &fam[..] {
-        "windows" | "unix" => ret.push(attr::mk_word_item(token::intern(&fam))),
-        _ => (),
+    let mut ret = HashSet::new();
+    // Target bindings.
+    ret.insert((token::intern("target_os"), Some(intern(os))));
+    ret.insert((token::intern("target_family"), Some(fam.clone())));
+    ret.insert((token::intern("target_arch"), Some(intern(arch))));
+    ret.insert((token::intern("target_endian"), Some(intern(end))));
+    ret.insert((token::intern("target_pointer_width"), Some(intern(wordsz))));
+    ret.insert((token::intern("target_env"), Some(intern(env))));
+    ret.insert((token::intern("target_vendor"), Some(intern(vendor))));
+    if &fam == "windows" || &fam == "unix" {
+        ret.insert((token::intern(&fam), None));
     }
     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] {
         if i <= max_atomic_width {
             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 {
-                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 {
-        ret.push(attr::mk_word_item(token::intern("debug_assertions")));
+        ret.insert((token::intern("debug_assertions"), None));
     }
     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;
 }
 
-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,
                            mut user_cfg: ast::CrateConfig)
                            -> ast::CrateConfig {
@@ -994,11 +986,10 @@ pub fn build_configuration(sess: &Session,
     let default_cfg = default_configuration(sess);
     // If the user wants a test runner, then add the test cfg
     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<_>>();
-    v.extend_from_slice(&default_cfg[..]);
-    v
+    user_cfg.extend(default_cfg.iter().cloned());
+    user_cfg
 }
 
 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());
 
         if !parser.reader.is_eof() {
-            early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}",
-                                                             s))
+            early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", 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>()
 }
 
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 7e60c40220f..e0a2eb6ae5e 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -95,12 +95,11 @@ use std::str;
 use std::sync::{Arc, Mutex};
 use std::thread;
 
-use syntax::{ast, json};
+use syntax::ast;
 use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
 use syntax::feature_gate::{GatedCfg, UnstableFeatures};
 use syntax::parse::{self, PResult};
-use syntax_pos::MultiSpan;
-use errors::emitter::Emitter;
+use syntax_pos::{DUMMY_SP, MultiSpan};
 
 #[cfg(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 {
     fn early_callback(&mut self,
                       matches: &getopts::Matches,
                       _: &config::Options,
-                      cfg: &ast::CrateConfig,
+                      _: &ast::CrateConfig,
                       descriptions: &errors::registry::Registry,
                       output: ErrorOutputType)
                       -> Compilation {
@@ -413,7 +386,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
             return Compilation::Stop;
         }
 
-        check_cfg(cfg, output);
         Compilation::Continue
     }
 
@@ -640,24 +612,26 @@ impl RustcDefaultCalls {
                     let allow_unstable_cfg = UnstableFeatures::from_environment()
                         .is_nightly_build();
 
-                    for cfg in &sess.parse_sess.config {
-                        if !allow_unstable_cfg && GatedCfg::gate(cfg).is_some() {
+                    let mut cfgs = Vec::new();
+                    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;
                         }
 
-                        if cfg.is_word() {
-                            println!("{}", cfg.name());
-                        } 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())
+                        cfgs.push(if let &Some(ref value) = value {
+                            format!("{}=\"{}\"", name, value)
                         } else {
-                            // There also shouldn't be literals.
-                            panic!("Found an unexpected literal in cfg attribute '{}'!", cfg.name())
-                        }
+                            format!("{}", name)
+                        });
+                    }
+
+                    cfgs.sort();
+                    for cfg in cfgs {
+                        println!("{}", cfg);
                     }
                 }
                 PrintRequest::TargetCPUs => {
diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs
index 436b44d8b03..34073dfd24d 100644
--- a/src/librustc_driver/target_features.rs
+++ b/src/librustc_driver/target_features.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::{ast, attr};
+use syntax::ast;
 use llvm::LLVMRustHasFeature;
 use rustc::session::Session;
 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 {
         assert_eq!(feat.chars().last(), Some('\0'));
         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 {
-        cfg.push(attr::mk_name_value_item_str(tf.clone(), intern("crt-static")));
+        cfg.insert((tf, Some(intern("crt-static"))));
     }
 }
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 0cd1c88fb87..c22416e1120 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -48,7 +48,7 @@ use rustc::hir::def_id::DefId;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use syntax::ast::{self, Attribute, NestedMetaItem};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
-use syntax::parse::token::InternedString;
+use syntax::parse::token;
 use syntax_pos::Span;
 use rustc::ty::TyCtxt;
 use ich::Fingerprint;
@@ -88,12 +88,11 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
 }
 
 impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
-
     fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
         for item in attr.meta_item_list().unwrap_or(&[]) {
             if item.check_name(LABEL) {
                 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,
                     Err(()) => {
                         self.tcx.sess.span_fatal(
@@ -276,13 +275,7 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool {
         if item.check_name(CFG) {
             let value = expect_associated_value(tcx, item);
             debug!("check_config: searching for cfg {:?}", value);
-            for cfg in &config[..] {
-                if cfg.check_name(&value[..]) {
-                    debug!("check_config: matched {:?}", cfg);
-                    return true;
-                }
-            }
-            return false;
+            return config.contains(&(value, None));
         }
     }
 
@@ -291,9 +284,9 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool {
         &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() {
-        value
+        token::intern(&value)
     } else {
         let msg = if let Some(name) = item.name() {
             format!("associated value expected for `{}`", name)
diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_trans/assert_module_sources.rs
index 264ed4cd12f..0bdf66e4589 100644
--- a/src/librustc_trans/assert_module_sources.rs
+++ b/src/librustc_trans/assert_module_sources.rs
@@ -29,7 +29,7 @@
 
 use rustc::ty::TyCtxt;
 use syntax::ast;
-use syntax::parse::token::InternedString;
+use syntax::parse::token;
 
 use {ModuleSource, ModuleTranslation};
 
@@ -77,7 +77,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
         }
 
         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 {
             Some(m) => m,
             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(&[]) {
             if item.check_name(name) {
                 if let Some(value) = item.value_str() {
-                    return value;
+                    return token::intern(&value);
                 } else {
                     self.tcx.sess.span_fatal(
                         item.span,
@@ -137,7 +137,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
         let config = &self.tcx.sess.parse_sess.config;
         let value = self.field(attr, CFG);
         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");
             return true;
         }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 8de843fdcb8..3664cc8e064 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -25,6 +25,7 @@ use print::pprust;
 use ptr::P;
 use tokenstream::{TokenTree};
 
+use std::collections::HashSet;
 use std::fmt;
 use std::rc::Rc;
 use std::u32;
@@ -485,7 +486,7 @@ pub struct WhereEqPredicate {
 
 /// The set of MetaItems that define the compilation environment of the crate,
 /// 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)]
 pub struct Crate {
@@ -519,7 +520,7 @@ pub type MetaItem = Spanned<MetaItemKind>;
 /// A compile-time attribute item.
 ///
 /// 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 {
     /// Word meta item.
     ///
@@ -535,34 +536,6 @@ pub enum MetaItemKind {
     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 (`{ .. }`).
 ///
 /// E.g. `{ .. }` as in `fn foo() { .. }`
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 220ecf52ae0..f84199fb29e 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -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 {
     debug!("attr::list_contains_name (name={})", name);
     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)) {
                 gated_cfg.check_and_emit(sess, feats);
             }
-            contains(&sess.config, cfg)
+            sess.config.contains(&(cfg.name(), cfg.value_str()))
         }
     }
 }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 12408c7d3c9..7feb745259c 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -22,6 +22,7 @@ use str::char_at;
 use tokenstream;
 
 use std::cell::RefCell;
+use std::collections::HashSet;
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
@@ -64,7 +65,7 @@ impl ParseSess {
         ParseSess {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(),
-            config: Vec::new(),
+            config: HashSet::new(),
             included_mod_stack: RefCell::new(vec![]),
             code_map: code_map
         }