about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo.net>2016-08-09 08:44:11 -0400
committerMichael Woerister <michaelwoerister@posteo.net>2016-08-11 09:56:00 -0400
commit65eb024542835c0235c31ef0e2381d155c797b03 (patch)
treebdd96b410a0a354aad5f762a61e2bd72b1540eb1
parentd3578ab742129a8aae8461f015d6cc36d85e65cc (diff)
Remove the 'cfg' field from session::config::Options.
The 'cfg' in the Options struct is only the commandline-specified
subset of the crate configuration and it's almost always wrong to
read that instead of the CrateConfig in HIR crate node.
-rw-r--r--src/librustc/session/config.rs226
-rw-r--r--src/librustc_driver/driver.rs5
-rw-r--r--src/librustc_driver/lib.rs38
-rw-r--r--src/librustc_metadata/creader.rs10
-rw-r--r--src/librustc_metadata/macro_import.rs8
-rw-r--r--src/librustc_plugin/load.rs10
-rw-r--r--src/librustdoc/core.rs3
-rw-r--r--src/librustdoc/test.rs6
-rw-r--r--src/test/run-make/issue-19371/foo.rs4
-rw-r--r--src/test/run-pass-fulldeps/compiler-calls.rs4
10 files changed, 74 insertions, 240 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index e337c1232aa..a1e30cbaae9 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -269,15 +269,6 @@ top_level_options!(
 
         target_triple: String [TRACKED],
 
-        // User-specified cfg meta items. The compiler itself will add additional
-        // items to the crate config, and during parsing the entire crate config
-        // will be added to the crate AST node.  This should not be used for
-        // anything except building the full crate config prior to parsing.
-        // FIXME(mw): If we could be entirely sure that the `cfg` only ever
-        //            influenced which HIR nodes get filtered out, we wouldn't
-        //            need to track this separately. However, we can't rely on
-        //            this (see `debug_assertions` above).
-        cfg: ast::CrateConfig [TRACKED],
         test: bool [TRACKED],
         error_format: ErrorOutputType [UNTRACKED],
         mir_opt_level: usize [TRACKED],
@@ -438,7 +429,6 @@ pub fn basic_options() -> Options {
         search_paths: SearchPaths::new(),
         maybe_sysroot: None,
         target_triple: host_triple().to_string(),
-        cfg: Vec::new(),
         test: false,
         mir_opt_level: 1,
         incremental: None,
@@ -1007,11 +997,12 @@ pub fn append_configuration(cfg: &mut ast::CrateConfig,
     }
 }
 
-pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
+pub fn build_configuration(sess: &Session,
+                           mut user_cfg: ast::CrateConfig)
+                           -> ast::CrateConfig {
     // Combine the configuration requested by the session (command line) with
     // some default and generated configuration items
     let default_cfg = default_configuration(sess);
-    let mut user_cfg = sess.opts.cfg.clone();
     // If the user wants a test runner, then add the test cfg
     if sess.opts.test {
         append_configuration(&mut user_cfg, InternedString::new("test"))
@@ -1273,7 +1264,8 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
     }).collect::<ast::CrateConfig>()
 }
 
-pub fn build_session_options(matches: &getopts::Matches) -> Options {
+pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
+                                              -> (Options, ast::CrateConfig) {
     let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
         Some("auto")   => ColorConfig::Auto,
         Some("always") => ColorConfig::Always,
@@ -1534,7 +1526,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m));
 
-    Options {
+    (Options {
         crate_types: crate_types,
         optimize: opt_level,
         debuginfo: debuginfo,
@@ -1545,7 +1537,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         search_paths: search_paths,
         maybe_sysroot: sysroot_opt,
         target_triple: target,
-        cfg: cfg,
         test: test,
         mir_opt_level: mir_opt_level,
         incremental: incremental,
@@ -1559,7 +1550,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         libs: libs,
         unstable_features: get_unstable_features_setting(),
         debug_assertions: debug_assertions,
-    }
+    },
+    cfg)
 }
 
 pub fn get_unstable_features_setting() -> UnstableFeatures {
@@ -1707,10 +1699,7 @@ mod dep_tracking {
     use std::path::PathBuf;
     use super::{Passes, PanicStrategy, CrateType, OptLevel, DebugInfoLevel,
                 OutputTypes, Externs, ErrorOutputType};
-    use syntax::ast;
     use syntax::feature_gate::UnstableFeatures;
-    use syntax::parse::token::InternedString;
-    use syntax::ptr::P;
 
     pub trait DepTrackingHash {
         fn hash(&self, &mut SipHasher, ErrorOutputType);
@@ -1775,64 +1764,6 @@ mod dep_tracking {
         }
     }
 
-    fn sorted_meta_items(items: &[P<ast::MetaItem>]) -> Vec<&ast::MetaItem> {
-        // Sort subitems so the hash does not depend on their order
-        let mut items: Vec<&ast::MetaItem> = items.iter()
-                                             .map(|r| &**r)
-                                             .collect();
-        items.sort_by_key(meta_item_sort_key);
-        return items;
-
-        fn meta_item_sort_key(item: &&ast::MetaItem) -> InternedString {
-            match item.node {
-                ast::MetaItemKind::Word(ref s) |
-                ast::MetaItemKind::NameValue(ref s, _) |
-                ast::MetaItemKind::List(ref s, _) => s.clone()
-            }
-        }
-    }
-
-    impl DepTrackingHash for ast::MetaItem {
-        fn hash(&self, hasher: &mut SipHasher, error_format: ErrorOutputType) {
-            // ignoring span information, it doesn't matter here
-            match self.node {
-                ast::MetaItemKind::Word(ref s) => {
-                    Hash::hash("Word", hasher);
-                    Hash::hash(&s.len(), hasher);
-                    Hash::hash(s, hasher);
-                }
-                ast::MetaItemKind::NameValue(ref s, ref lit) => {
-                    Hash::hash("NameValue", hasher);
-                    Hash::hash(&s.len(), hasher);
-                    Hash::hash(s, hasher);
-                    Hash::hash(&lit.node, hasher);
-                }
-                ast::MetaItemKind::List(ref s, ref items) => {
-                    Hash::hash("List", hasher);
-                    Hash::hash(&s.len(), hasher);
-                    Hash::hash(s, hasher);
-                    // Sort subitems so the hash does not depend on their order
-                    let sorted = sorted_meta_items(&items[..]);
-                    for (index, item) in sorted.iter().enumerate() {
-                        Hash::hash(&index, hasher);
-                        DepTrackingHash::hash(*item, hasher, error_format);
-                    }
-                }
-            }
-        }
-    }
-
-    impl DepTrackingHash for ast::CrateConfig {
-        fn hash(&self, hasher: &mut SipHasher, error_format: ErrorOutputType) {
-            // Sort subitems so the hash does not depend on their order
-            let sorted = sorted_meta_items(&self[..]);
-            for (index, item) in sorted.iter().enumerate() {
-                Hash::hash(&index, hasher);
-                DepTrackingHash::hash(*item, hasher, error_format);
-            }
-        }
-    }
-
     impl<T1, T2> DepTrackingHash for (T1, T2)
         where T1: DepTrackingHash,
               T2: DepTrackingHash
@@ -1866,19 +1797,15 @@ mod tests {
     use getopts::{getopts, OptGroup};
     use lint;
     use middle::cstore::{self, DummyCrateStore};
-    use session::config::{build_configuration, build_session_options};
+    use session::config::{build_configuration, build_session_options_and_crate_config};
     use session::build_session;
     use std::collections::{BTreeMap, BTreeSet};
     use std::iter::FromIterator;
     use std::path::PathBuf;
     use std::rc::Rc;
     use super::{OutputType, OutputTypes, Externs, PanicStrategy};
-    use syntax::ast::{self, MetaItemKind};
     use syntax::attr;
     use syntax::attr::AttrMetaMethods;
-    use syntax::codemap::dummy_spanned;
-    use syntax::parse::token::InternedString;
-    use syntax::ptr::P;
 
     fn optgroups() -> Vec<OptGroup> {
         super::rustc_optgroups().into_iter()
@@ -1904,9 +1831,9 @@ mod tests {
               Err(f) => panic!("test_switch_implies_cfg_test: {}", f)
             };
         let registry = errors::registry::Registry::new(&[]);
-        let sessopts = build_session_options(matches);
+        let (sessopts, cfg) = build_session_options_and_crate_config(matches);
         let sess = build_session(sessopts, &dep_graph, None, registry, Rc::new(DummyCrateStore));
-        let cfg = build_configuration(&sess);
+        let cfg = build_configuration(&sess, cfg);
         assert!((attr::contains_name(&cfg[..], "test")));
     }
 
@@ -1924,10 +1851,10 @@ mod tests {
               }
             };
         let registry = errors::registry::Registry::new(&[]);
-        let sessopts = build_session_options(matches);
+        let (sessopts, cfg) = build_session_options_and_crate_config(matches);
         let sess = build_session(sessopts, &dep_graph, None, registry,
                                  Rc::new(DummyCrateStore));
-        let cfg = build_configuration(&sess);
+        let cfg = build_configuration(&sess, cfg);
         let mut test_items = cfg.iter().filter(|m| m.name() == "test");
         assert!(test_items.next().is_some());
         assert!(test_items.next().is_none());
@@ -1941,7 +1868,7 @@ mod tests {
                 "-Awarnings".to_string()
             ], &optgroups()).unwrap();
             let registry = errors::registry::Registry::new(&[]);
-            let sessopts = build_session_options(&matches);
+            let (sessopts, _) = build_session_options_and_crate_config(&matches);
             let sess = build_session(sessopts, &dep_graph, None, registry,
                                      Rc::new(DummyCrateStore));
             assert!(!sess.diagnostic().can_emit_warnings);
@@ -1953,7 +1880,7 @@ mod tests {
                 "-Dwarnings".to_string()
             ], &optgroups()).unwrap();
             let registry = errors::registry::Registry::new(&[]);
-            let sessopts = build_session_options(&matches);
+            let (sessopts, _) = build_session_options_and_crate_config(&matches);
             let sess = build_session(sessopts, &dep_graph, None, registry,
                                      Rc::new(DummyCrateStore));
             assert!(sess.diagnostic().can_emit_warnings);
@@ -1964,7 +1891,7 @@ mod tests {
                 "-Adead_code".to_string()
             ], &optgroups()).unwrap();
             let registry = errors::registry::Registry::new(&[]);
-            let sessopts = build_session_options(&matches);
+            let (sessopts, _) = build_session_options_and_crate_config(&matches);
             let sess = build_session(sessopts, &dep_graph, None, registry,
                                      Rc::new(DummyCrateStore));
             assert!(sess.diagnostic().can_emit_warnings);
@@ -2142,127 +2069,6 @@ mod tests {
     }
 
     #[test]
-    fn test_crate_config_tracking_hash_different_values() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
-        let mut v4 = super::basic_options();
-
-        // Reference value
-        v1.cfg = vec![
-            P(dummy_spanned(MetaItemKind::Word(InternedString::new("a")))),
-            P(dummy_spanned(MetaItemKind::List(InternedString::new("b"),
-                    vec![
-                        P(dummy_spanned(MetaItemKind::Word(InternedString::new("c")))),
-                        P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("d"),
-                                                    dummy_spanned(ast::LitKind::Byte(1))))),
-                    ]))),
-            P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("e"),
-                                                    dummy_spanned(ast::LitKind::Byte(2))))),
-        ];
-
-        // Change a label
-        v2.cfg = vec![
-            P(dummy_spanned(MetaItemKind::Word(InternedString::new("a")))),
-            P(dummy_spanned(MetaItemKind::List(InternedString::new("X"),
-                    vec![
-                        P(dummy_spanned(MetaItemKind::Word(InternedString::new("c")))),
-                        P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("d"),
-                                                    dummy_spanned(ast::LitKind::Byte(1))))),
-                    ]))),
-            P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("e"),
-                                                    dummy_spanned(ast::LitKind::Byte(2))))),
-        ];
-
-        // Change a literal
-        v3.cfg = vec![
-            P(dummy_spanned(MetaItemKind::Word(InternedString::new("a")))),
-            P(dummy_spanned(MetaItemKind::List(InternedString::new("X"),
-                    vec![
-                        P(dummy_spanned(MetaItemKind::Word(InternedString::new("c")))),
-                        P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("d"),
-                                                    dummy_spanned(ast::LitKind::Byte(99))))),
-                    ]))),
-            P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("e"),
-                                                    dummy_spanned(ast::LitKind::Byte(2))))),
-        ];
-
-        // Remove something
-        v4.cfg = vec![
-            P(dummy_spanned(MetaItemKind::Word(InternedString::new("a")))),
-            P(dummy_spanned(MetaItemKind::List(InternedString::new("X"),
-                    vec![
-                        P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("d"),
-                                                    dummy_spanned(ast::LitKind::Byte(99))))),
-                    ]))),
-            P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("e"),
-                                                    dummy_spanned(ast::LitKind::Byte(2))))),
-        ];
-
-        assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
-        assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
-        assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
-
-        // Check clone
-        assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-        assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-        assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
-        assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
-    }
-
-    #[test]
-    fn test_crate_config_tracking_hash_different_order() {
-        let mut v1 = super::basic_options();
-        let mut v2 = super::basic_options();
-        let mut v3 = super::basic_options();
-
-        // Reference value
-        v1.cfg = vec![
-            P(dummy_spanned(MetaItemKind::Word(InternedString::new("a")))),
-            P(dummy_spanned(MetaItemKind::List(InternedString::new("b"),
-                    vec![
-                        P(dummy_spanned(MetaItemKind::Word(InternedString::new("c")))),
-                        P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("d"),
-                                                    dummy_spanned(ast::LitKind::Byte(1))))),
-                    ]))),
-            P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("e"),
-                                                    dummy_spanned(ast::LitKind::Byte(2))))),
-        ];
-
-        v2.cfg = vec![
-            P(dummy_spanned(MetaItemKind::List(InternedString::new("b"),
-                    vec![
-                        P(dummy_spanned(MetaItemKind::Word(InternedString::new("c")))),
-                        P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("d"),
-                                                    dummy_spanned(ast::LitKind::Byte(1))))),
-                    ]))),
-            P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("e"),
-                                                    dummy_spanned(ast::LitKind::Byte(2))))),
-            P(dummy_spanned(MetaItemKind::Word(InternedString::new("a")))),
-        ];
-
-        v3.cfg = vec![
-            P(dummy_spanned(MetaItemKind::Word(InternedString::new("a")))),
-            P(dummy_spanned(MetaItemKind::List(InternedString::new("b"),
-                    vec![
-                        P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("d"),
-                                                    dummy_spanned(ast::LitKind::Byte(1))))),
-                        P(dummy_spanned(MetaItemKind::Word(InternedString::new("c")))),
-                    ]))),
-            P(dummy_spanned(MetaItemKind::NameValue(InternedString::new("e"),
-                                                    dummy_spanned(ast::LitKind::Byte(2))))),
-        ];
-
-        assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
-        assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
-
-        // Check clone
-        assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
-        assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
-        assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
-    }
-
-    #[test]
     fn test_search_paths_tracking_hash_different_values() {
         let mut v1 = super::basic_options();
         let mut v2 = super::basic_options();
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index aa794829be2..568d98ac8d6 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -667,7 +667,10 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
             trace_mac: sess.opts.debugging_opts.trace_macros,
             should_test: sess.opts.test,
         };
-        let mut loader = macro_import::MacroLoader::new(sess, &cstore, crate_name);
+        let mut loader = macro_import::MacroLoader::new(sess,
+                                                        &cstore,
+                                                        crate_name,
+                                                        krate.config.clone());
         let mut ecx = syntax::ext::base::ExtCtxt::new(&sess.parse_sess,
                                                       krate.config.clone(),
                                                       cfg,
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index b2a6df8d345..6f57ae29418 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -181,7 +181,7 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String],
         None => return (Ok(()), None),
     };
 
-    let sopts = config::build_session_options(&matches);
+    let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
 
     if sopts.debugging_opts.debug_llvm {
         unsafe { llvm::LLVMRustSetDebug(1); }
@@ -191,6 +191,7 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String],
 
     do_or_return!(callbacks.early_callback(&matches,
                                            &sopts,
+                                           &cfg,
                                            &descriptions,
                                            sopts.error_format),
                                            None);
@@ -198,7 +199,7 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String],
     let (odir, ofile) = make_output(&matches);
     let (input, input_file_path) = match make_input(&matches.free) {
         Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
-        None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) {
+        None => match callbacks.no_input(&matches, &sopts, &cfg, &odir, &ofile, &descriptions) {
             Some((input, input_file_path)) => (input, input_file_path),
             None => return (Ok(()), None),
         },
@@ -214,10 +215,11 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String],
                                                    cstore.clone(),
                                                    codemap);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-    let mut cfg = config::build_configuration(&sess);
+    let mut cfg = config::build_configuration(&sess, cfg);
     target_features::add_configuration(&mut cfg, &sess);
 
-    do_or_return!(callbacks.late_callback(&matches, &sess, &input, &odir, &ofile), Some(sess));
+    do_or_return!(callbacks.late_callback(&matches, &sess, &cfg, &input, &odir, &ofile),
+                  Some(sess));
 
     let plugins = sess.opts.debugging_opts.extra_plugins.clone();
     let control = callbacks.build_controller(&sess, &matches);
@@ -297,6 +299,7 @@ pub trait CompilerCalls<'a> {
     fn early_callback(&mut self,
                       _: &getopts::Matches,
                       _: &config::Options,
+                      _: &ast::CrateConfig,
                       _: &errors::registry::Registry,
                       _: ErrorOutputType)
                       -> Compilation {
@@ -309,6 +312,7 @@ pub trait CompilerCalls<'a> {
     fn late_callback(&mut self,
                      _: &getopts::Matches,
                      _: &Session,
+                     _: &ast::CrateConfig,
                      _: &Input,
                      _: &Option<PathBuf>,
                      _: &Option<PathBuf>)
@@ -334,6 +338,7 @@ pub trait CompilerCalls<'a> {
     fn no_input(&mut self,
                 _: &getopts::Matches,
                 _: &config::Options,
+                _: &ast::CrateConfig,
                 _: &Option<PathBuf>,
                 _: &Option<PathBuf>,
                 _: &errors::registry::Registry)
@@ -375,7 +380,7 @@ fn handle_explain(code: &str,
     }
 }
 
-fn check_cfg(sopts: &config::Options,
+fn check_cfg(cfg: &ast::CrateConfig,
              output: ErrorOutputType) {
     let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
@@ -386,7 +391,7 @@ fn check_cfg(sopts: &config::Options,
     let handler = errors::Handler::with_emitter(true, false, emitter);
 
     let mut saw_invalid_predicate = false;
-    for item in sopts.cfg.iter() {
+    for item in cfg.iter() {
         if item.is_meta_item_list() {
             saw_invalid_predicate = true;
             handler.emit(&MultiSpan::new(),
@@ -404,7 +409,8 @@ fn check_cfg(sopts: &config::Options,
 impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
     fn early_callback(&mut self,
                       matches: &getopts::Matches,
-                      sopts: &config::Options,
+                      _: &config::Options,
+                      cfg: &ast::CrateConfig,
                       descriptions: &errors::registry::Registry,
                       output: ErrorOutputType)
                       -> Compilation {
@@ -413,13 +419,14 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
             return Compilation::Stop;
         }
 
-        check_cfg(sopts, output);
+        check_cfg(cfg, output);
         Compilation::Continue
     }
 
     fn no_input(&mut self,
                 matches: &getopts::Matches,
                 sopts: &config::Options,
+                cfg: &ast::CrateConfig,
                 odir: &Option<PathBuf>,
                 ofile: &Option<PathBuf>,
                 descriptions: &errors::registry::Registry)
@@ -440,7 +447,13 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                     descriptions.clone(),
                     cstore.clone());
                 rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-                let should_stop = RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile);
+                let mut cfg = config::build_configuration(&sess, cfg.clone());
+                target_features::add_configuration(&mut cfg, &sess);
+                let should_stop = RustcDefaultCalls::print_crate_info(&sess,
+                                                                      &cfg,
+                                                                      None,
+                                                                      odir,
+                                                                      ofile);
                 if should_stop == Compilation::Stop {
                     return None;
                 }
@@ -456,11 +469,12 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
     fn late_callback(&mut self,
                      matches: &getopts::Matches,
                      sess: &Session,
+                     cfg: &ast::CrateConfig,
                      input: &Input,
                      odir: &Option<PathBuf>,
                      ofile: &Option<PathBuf>)
                      -> Compilation {
-        RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile)
+        RustcDefaultCalls::print_crate_info(sess, cfg, Some(input), odir, ofile)
             .and_then(|| RustcDefaultCalls::list_metadata(sess, matches, input))
     }
 
@@ -579,6 +593,7 @@ impl RustcDefaultCalls {
 
 
     fn print_crate_info(sess: &Session,
+                        cfg: &ast::CrateConfig,
                         input: Option<&Input>,
                         odir: &Option<PathBuf>,
                         ofile: &Option<PathBuf>)
@@ -631,9 +646,6 @@ impl RustcDefaultCalls {
                     }
                 }
                 PrintRequest::Cfg => {
-                    let mut cfg = config::build_configuration(&sess);
-                    target_features::add_configuration(&mut cfg, &sess);
-
                     let allow_unstable_cfg = match get_unstable_features_setting() {
                         UnstableFeatures::Disallow => false,
                         _ => true,
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 0b60fc386a7..4a656b180f2 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -56,6 +56,7 @@ pub struct CrateReader<'a> {
     next_crate_num: ast::CrateNum,
     foreign_item_map: FnvHashMap<String, Vec<ast::NodeId>>,
     local_crate_name: String,
+    local_crate_config: ast::CrateConfig,
 }
 
 impl<'a> visit::Visitor for LocalCrateReader<'a> {
@@ -152,13 +153,16 @@ enum LoadResult {
 impl<'a> CrateReader<'a> {
     pub fn new(sess: &'a Session,
                cstore: &'a CStore,
-               local_crate_name: &str) -> CrateReader<'a> {
+               local_crate_name: &str,
+               local_crate_config: ast::CrateConfig)
+               -> CrateReader<'a> {
         CrateReader {
             sess: sess,
             cstore: cstore,
             next_crate_num: cstore.next_crate_num(),
             foreign_item_map: FnvHashMap(),
             local_crate_name: local_crate_name.to_owned(),
+            local_crate_config: local_crate_config,
         }
     }
 
@@ -561,7 +565,7 @@ impl<'a> CrateReader<'a> {
                 // NB: Don't use parse::parse_tts_from_source_str because it parses with
                 // quote_depth > 0.
                 let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
-                                                              self.sess.opts.cfg.clone(),
+                                                              self.local_crate_config.clone(),
                                                               source_name.clone(),
                                                               body);
                 let lo = p.span.lo;
@@ -863,7 +867,7 @@ impl<'a> LocalCrateReader<'a> {
         LocalCrateReader {
             sess: sess,
             cstore: cstore,
-            creader: CrateReader::new(sess, cstore, local_crate_name),
+            creader: CrateReader::new(sess, cstore, local_crate_name, krate.config.clone()),
             krate: krate,
             definitions: defs,
         }
diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs
index 4be044c1df3..b2a2dcf90fa 100644
--- a/src/librustc_metadata/macro_import.rs
+++ b/src/librustc_metadata/macro_import.rs
@@ -29,10 +29,14 @@ pub struct MacroLoader<'a> {
 }
 
 impl<'a> MacroLoader<'a> {
-    pub fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> MacroLoader<'a> {
+    pub fn new(sess: &'a Session,
+               cstore: &'a CStore,
+               crate_name: &str,
+               crate_config: ast::CrateConfig)
+               -> MacroLoader<'a> {
         MacroLoader {
             sess: sess,
-            reader: CrateReader::new(sess, cstore, crate_name),
+            reader: CrateReader::new(sess, cstore, crate_name, crate_config),
         }
     }
 }
diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs
index a3cd9b5da02..fb68eae9647 100644
--- a/src/librustc_plugin/load.rs
+++ b/src/librustc_plugin/load.rs
@@ -49,7 +49,7 @@ pub fn load_plugins(sess: &Session,
                     krate: &ast::Crate,
                     crate_name: &str,
                     addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
-    let mut loader = PluginLoader::new(sess, cstore, crate_name);
+    let mut loader = PluginLoader::new(sess, cstore, crate_name, krate.config.clone());
 
     // do not report any error now. since crate attributes are
     // not touched by expansion, every use of plugin without
@@ -90,10 +90,14 @@ pub fn load_plugins(sess: &Session,
 }
 
 impl<'a> PluginLoader<'a> {
-    fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> PluginLoader<'a> {
+    fn new(sess: &'a Session,
+           cstore: &'a CStore,
+           crate_name: &str,
+           crate_config: ast::CrateConfig)
+            -> PluginLoader<'a> {
         PluginLoader {
             sess: sess,
-            reader: CrateReader::new(sess, cstore, crate_name),
+            reader: CrateReader::new(sess, cstore, crate_name, crate_config),
             plugins: vec![],
         }
     }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 863b787c58d..10736d2c827 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -119,7 +119,6 @@ pub fn run_core(search_paths: SearchPaths,
         lint_cap: Some(lint::Allow),
         externs: externs,
         target_triple: triple.unwrap_or(config::host_triple().to_string()),
-        cfg: config::parse_cfgspecs(cfgs),
         // Ensure that rustdoc works even if rustc is feature-staged
         unstable_features: UnstableFeatures::Allow,
         ..config::basic_options().clone()
@@ -138,7 +137,7 @@ pub fn run_core(search_paths: SearchPaths,
                                        codemap, cstore.clone());
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
-    let mut cfg = config::build_configuration(&sess);
+    let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
     target_features::add_configuration(&mut cfg, &sess);
 
     let krate = panictry!(driver::phase_1_parse_input(&sess, cfg, &input));
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 12749c857ab..7d1dbbe5dc0 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -90,8 +90,7 @@ pub fn run(input: &str,
                                        cstore.clone());
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
-    let mut cfg = config::build_configuration(&sess);
-    cfg.extend(config::parse_cfgspecs(cfgs.clone()));
+    let cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
     let krate = panictry!(driver::phase_1_parse_input(&sess, cfg, &input));
     let driver::ExpansionResult { defs, mut hir_forest, .. } = {
         phase_2_configure_and_expand(
@@ -247,8 +246,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
     let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
     let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
     let mut control = driver::CompileController::basic();
-    let mut cfg = config::build_configuration(&sess);
-    cfg.extend(config::parse_cfgspecs(cfgs.clone()));
+    let cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
     let out = Some(outdir.lock().unwrap().path().to_path_buf());
 
     if no_run {
diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs
index f501c06a823..35043bdaddf 100644
--- a/src/test/run-make/issue-19371/foo.rs
+++ b/src/test/run-make/issue-19371/foo.rs
@@ -52,7 +52,7 @@ fn main() {
 
 fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
     let mut opts = basic_options();
-    opts.output_types = OutputTypes::new([(OutputType::Exe, None)]);
+    opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
     opts.maybe_sysroot = Some(sysroot);
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
@@ -65,7 +65,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
 
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
     let (sess, cstore) = basic_sess(sysroot);
-    let cfg = build_configuration(&sess);
+    let cfg = build_configuration(&sess, vec![]);
     let control = CompileController::basic();
 
     compile_input(&sess, &cstore,
diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs
index ff57e9d6b73..775ba38004e 100644
--- a/src/test/run-pass-fulldeps/compiler-calls.rs
+++ b/src/test/run-pass-fulldeps/compiler-calls.rs
@@ -24,6 +24,7 @@ extern crate rustc_errors as errors;
 use rustc::session::Session;
 use rustc::session::config::{self, Input};
 use rustc_driver::{driver, CompilerCalls, Compilation};
+use syntax::ast;
 
 use std::path::PathBuf;
 
@@ -35,6 +36,7 @@ impl<'a> CompilerCalls<'a> for TestCalls {
     fn early_callback(&mut self,
                       _: &getopts::Matches,
                       _: &config::Options,
+                      _: &ast::CrateConfig,
                       _: &errors::registry::Registry,
                       _: config::ErrorOutputType)
                       -> Compilation {
@@ -45,6 +47,7 @@ impl<'a> CompilerCalls<'a> for TestCalls {
     fn late_callback(&mut self,
                      _: &getopts::Matches,
                      _: &Session,
+                     _: &ast::CrateConfig,
                      _: &Input,
                      _: &Option<PathBuf>,
                      _: &Option<PathBuf>)
@@ -62,6 +65,7 @@ impl<'a> CompilerCalls<'a> for TestCalls {
     fn no_input(&mut self,
                 _: &getopts::Matches,
                 _: &config::Options,
+                _: &ast::CrateConfig,
                 _: &Option<PathBuf>,
                 _: &Option<PathBuf>,
                 _: &errors::registry::Registry)