about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ich/caching_codemap_view.rs6
-rw-r--r--src/librustc/session/config.rs6
-rw-r--r--src/librustc/session/mod.rs6
-rw-r--r--src/librustc/ty/context.rs21
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc_data_structures/indexed_vec.rs2
-rw-r--r--src/librustc_driver/driver.rs20
-rw-r--r--src/librustc_driver/lib.rs5
-rw-r--r--src/librustc_driver/pretty.rs20
-rw-r--r--src/librustc_driver/test.rs5
-rw-r--r--src/librustc_errors/lib.rs18
-rw-r--r--src/librustdoc/core.rs7
-rw-r--r--src/libserialize/collection_impls.rs24
-rw-r--r--src/libsyntax/attr.rs16
-rw-r--r--src/libsyntax/lib.rs1
15 files changed, 89 insertions, 70 deletions
diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs
index e3934590278..3caf308d652 100644
--- a/src/librustc/ich/caching_codemap_view.rs
+++ b/src/librustc/ich/caching_codemap_view.rs
@@ -78,11 +78,9 @@ impl<'cm> CachingCodemapView<'cm> {
         // If the entry doesn't point to the correct file, fix it up
         if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos {
             let file_valid;
-            let files = self.codemap.files();
-
-            if files.len() > 0 {
+            if self.codemap.files().len() > 0 {
                 let file_index = self.codemap.lookup_filemap_idx(pos);
-                let file = files[file_index].clone();
+                let file = self.codemap.files()[file_index].clone();
 
                 if pos >= file.start_pos && pos < file.end_pos {
                     cache_entry.file = file;
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 7e80139b791..6ad9bd94bf2 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1092,6 +1092,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "prints the llvm optimization passes being run"),
     ast_json: bool = (false, parse_bool, [UNTRACKED],
         "print the AST as JSON and halt"),
+    query_threads: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
+        "execute queries on a thread pool with N threads"),
     ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED],
         "print the pre-expansion AST as JSON and halt"),
     ls: bool = (false, parse_bool, [UNTRACKED],
@@ -1688,6 +1690,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         }
     }
 
+    if debugging_opts.query_threads == Some(0) {
+        early_error(error_format, "Value for query threads must be a positive nonzero integer");
+    }
+
     if codegen_units == Some(0) {
         early_error(error_format, "Value for codegen units must be a positive nonzero integer");
     }
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 60a218500ca..0de1c20dbde 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -725,6 +725,12 @@ impl Session {
         ret
     }
 
+    /// Returns the number of query threads that should be used for this
+    /// compilation
+    pub fn query_threads(&self) -> usize {
+        self.opts.debugging_opts.query_threads.unwrap_or(1)
+    }
+
     /// Returns the number of codegen units that should be used for this
     /// compilation
     pub fn codegen_units(&self) -> usize {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 5464fa601ec..b233156cf7f 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -76,6 +76,20 @@ use syntax_pos::Span;
 
 use hir;
 
+pub struct AllArenas<'tcx> {
+    pub global: GlobalArenas<'tcx>,
+    pub interner: DroplessArena,
+}
+
+impl<'tcx> AllArenas<'tcx> {
+    pub fn new() -> Self {
+        AllArenas {
+            global: GlobalArenas::new(),
+            interner: DroplessArena::new(),
+        }
+    }
+}
+
 /// Internal storage
 pub struct GlobalArenas<'tcx> {
     // internings
@@ -1120,8 +1134,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   cstore: &'tcx CrateStore,
                                   local_providers: ty::maps::Providers<'tcx>,
                                   extern_providers: ty::maps::Providers<'tcx>,
-                                  arenas: &'tcx GlobalArenas<'tcx>,
-                                  arena: &'tcx DroplessArena,
+                                  arenas: &'tcx AllArenas<'tcx>,
                                   resolutions: ty::Resolutions,
                                   hir: hir_map::Map<'tcx>,
                                   on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
@@ -1132,7 +1145,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
     {
         let data_layout = TargetDataLayout::parse(s);
-        let interners = CtxtInterners::new(arena);
+        let interners = CtxtInterners::new(&arenas.interner);
         let common_types = CommonTypes::new(&interners);
         let dep_graph = hir.dep_graph.clone();
         let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0);
@@ -1184,7 +1197,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         tls::enter_global(GlobalCtxt {
             sess: s,
             cstore,
-            global_arenas: arenas,
+            global_arenas: &arenas.global,
             global_interners: interners,
             dep_graph: dep_graph.clone(),
             on_disk_query_result_cache,
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 3ab322b55c7..e03e1237466 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -77,7 +77,7 @@ pub use self::sty::TypeVariants::*;
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
 
-pub use self::context::{TyCtxt, GlobalArenas, tls, keep_local};
+pub use self::context::{TyCtxt, GlobalArenas, AllArenas, tls, keep_local};
 pub use self::context::{Lift, TypeckTables};
 
 pub use self::instance::{Instance, InstanceDef};
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 19528a14038..753f12f400b 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -327,7 +327,7 @@ macro_rules! newtype_index {
 #[derive(Clone, PartialEq, Eq)]
 pub struct IndexVec<I: Idx, T> {
     pub raw: Vec<T>,
-    _marker: PhantomData<Fn(&I)>
+    _marker: PhantomData<fn(&I)>
 }
 
 // Whether `IndexVec` is `Send` depends only on the data,
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index a288ff6316f..c0bbab35e1e 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -22,7 +22,7 @@ use rustc::lint;
 use rustc::middle::{self, stability, reachable, resolve_lifetime};
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
-use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
+use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
 use rustc::traits;
 use rustc::util::common::{ErrorReported, time};
 use rustc_allocator as allocator;
@@ -62,7 +62,6 @@ use syntax::util::node_count::NodeCounter;
 use syntax_pos::FileName;
 use syntax;
 use syntax_ext;
-use arena::DroplessArena;
 
 use derive_registrar;
 use pretty::ReplaceBodyWithLoop;
@@ -184,8 +183,7 @@ pub fn compile_input(sess: &Session,
             return Ok(())
         }
 
-        let arena = DroplessArena::new();
-        let arenas = GlobalArenas::new();
+        let arenas = AllArenas::new();
 
         // Construct the HIR map
         let hir_map = time(sess.time_passes(),
@@ -200,7 +198,6 @@ pub fn compile_input(sess: &Session,
                                                                   sess,
                                                                   outdir,
                                                                   output,
-                                                                  &arena,
                                                                   &arenas,
                                                                   &cstore,
                                                                   &hir_map,
@@ -230,7 +227,6 @@ pub fn compile_input(sess: &Session,
                                     hir_map,
                                     analysis,
                                     resolutions,
-                                    &arena,
                                     &arenas,
                                     &crate_name,
                                     &outputs,
@@ -416,8 +412,7 @@ pub struct CompileState<'a, 'tcx: 'a> {
     pub output_filenames: Option<&'a OutputFilenames>,
     pub out_dir: Option<&'a Path>,
     pub out_file: Option<&'a Path>,
-    pub arena: Option<&'tcx DroplessArena>,
-    pub arenas: Option<&'tcx GlobalArenas<'tcx>>,
+    pub arenas: Option<&'tcx AllArenas<'tcx>>,
     pub expanded_crate: Option<&'a ast::Crate>,
     pub hir_crate: Option<&'a hir::Crate>,
     pub hir_map: Option<&'a hir_map::Map<'tcx>>,
@@ -437,7 +432,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
             session,
             out_dir: out_dir.as_ref().map(|s| &**s),
             out_file: None,
-            arena: None,
             arenas: None,
             krate: None,
             registry: None,
@@ -492,8 +486,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
                                 session: &'tcx Session,
                                 out_dir: &'a Option<PathBuf>,
                                 out_file: &'a Option<PathBuf>,
-                                arena: &'tcx DroplessArena,
-                                arenas: &'tcx GlobalArenas<'tcx>,
+                                arenas: &'tcx AllArenas<'tcx>,
                                 cstore: &'tcx CStore,
                                 hir_map: &'a hir_map::Map<'tcx>,
                                 analysis: &'a ty::CrateAnalysis,
@@ -505,7 +498,6 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
                                 -> Self {
         CompileState {
             crate_name: Some(crate_name),
-            arena: Some(arena),
             arenas: Some(arenas),
             cstore: Some(cstore),
             hir_map: Some(hir_map),
@@ -974,8 +966,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
                                                hir_map: hir_map::Map<'tcx>,
                                                mut analysis: ty::CrateAnalysis,
                                                resolutions: Resolutions,
-                                               arena: &'tcx DroplessArena,
-                                               arenas: &'tcx GlobalArenas<'tcx>,
+                                               arenas: &'tcx AllArenas<'tcx>,
                                                name: &str,
                                                output_filenames: &OutputFilenames,
                                                f: F)
@@ -1035,7 +1026,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
                              local_providers,
                              extern_providers,
                              arenas,
-                             arena,
                              resolutions,
                              hir_map,
                              query_result_on_disk_cache,
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 60857505c7a..5fa82365928 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -227,7 +227,7 @@ pub fn run_compiler<'a>(args: &[String],
         },
     };
 
-    let cstore = Rc::new(CStore::new(DefaultTransCrate::metadata_loader()));
+    let cstore = CStore::new(DefaultTransCrate::metadata_loader());
 
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
@@ -243,7 +243,7 @@ pub fn run_compiler<'a>(args: &[String],
 
     do_or_return!(callbacks.late_callback(&matches,
                                           &sess,
-                                          &*cstore,
+                                          &cstore,
                                           &input,
                                           &odir,
                                           &ofile), Some(sess));
@@ -580,7 +580,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                                                      &state.expanded_crate.take().unwrap(),
                                                      state.crate_name.unwrap(),
                                                      ppm,
-                                                     state.arena.unwrap(),
                                                      state.arenas.unwrap(),
                                                      state.output_filenames.unwrap(),
                                                      opt_uii.clone(),
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 4b51a0fbb83..76923be65cf 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -17,7 +17,7 @@ use self::NodesMatchingUII::*;
 
 use {abort_on_err, driver};
 
-use rustc::ty::{self, TyCtxt, GlobalArenas, Resolutions};
+use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
 use rustc::cfg;
 use rustc::cfg::graphviz::LabelledCFG;
 use rustc::middle::cstore::CrateStore;
@@ -51,8 +51,6 @@ use rustc::hir::map::blocks;
 use rustc::hir;
 use rustc::hir::print as pprust_hir;
 
-use arena::DroplessArena;
-
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpSourceMode {
     PpmNormal,
@@ -205,8 +203,7 @@ impl PpSourceMode {
                                                hir_map: &hir_map::Map<'tcx>,
                                                analysis: &ty::CrateAnalysis,
                                                resolutions: &Resolutions,
-                                               arena: &'tcx DroplessArena,
-                                               arenas: &'tcx GlobalArenas<'tcx>,
+                                               arenas: &'tcx AllArenas<'tcx>,
                                                output_filenames: &OutputFilenames,
                                                id: &str,
                                                f: F)
@@ -237,7 +234,6 @@ impl PpSourceMode {
                                                                  hir_map.clone(),
                                                                  analysis.clone(),
                                                                  resolutions.clone(),
-                                                                 arena,
                                                                  arenas,
                                                                  id,
                                                                  output_filenames,
@@ -914,8 +910,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                 krate: &ast::Crate,
                                                 crate_name: &str,
                                                 ppm: PpMode,
-                                                arena: &'tcx DroplessArena,
-                                                arenas: &'tcx GlobalArenas<'tcx>,
+                                                arenas: &'tcx AllArenas<'tcx>,
                                                 output_filenames: &OutputFilenames,
                                                 opt_uii: Option<UserIdentifiedItem>,
                                                 ofile: Option<&Path>) {
@@ -926,7 +921,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                             analysis,
                             resolutions,
                             crate_name,
-                            arena,
                             arenas,
                             output_filenames,
                             ppm,
@@ -965,7 +959,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            hir_map,
                                            analysis,
                                            resolutions,
-                                           arena,
                                            arenas,
                                            output_filenames,
                                            crate_name,
@@ -990,7 +983,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            hir_map,
                                            analysis,
                                            resolutions,
-                                           arena,
                                            arenas,
                                            output_filenames,
                                            crate_name,
@@ -1007,7 +999,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            hir_map,
                                            analysis,
                                            resolutions,
-                                           arena,
                                            arenas,
                                            output_filenames,
                                            crate_name,
@@ -1042,7 +1033,6 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            hir_map,
                                            analysis,
                                            resolutions,
-                                           arena,
                                            arenas,
                                            output_filenames,
                                            crate_name,
@@ -1073,8 +1063,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                        analysis: &ty::CrateAnalysis,
                                        resolutions: &Resolutions,
                                        crate_name: &str,
-                                       arena: &'tcx DroplessArena,
-                                       arenas: &'tcx GlobalArenas<'tcx>,
+                                       arenas: &'tcx AllArenas<'tcx>,
                                        output_filenames: &OutputFilenames,
                                        ppm: PpMode,
                                        uii: Option<UserIdentifiedItem>,
@@ -1096,7 +1085,6 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                      hir_map.clone(),
                                                      analysis.clone(),
                                                      resolutions.clone(),
-                                                     arena,
                                                      arenas,
                                                      crate_name,
                                                      output_filenames,
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index ded2fa01e59..6765ea5e67a 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -40,7 +40,6 @@ use errors::{Level, DiagnosticBuilder};
 use syntax::feature_gate::UnstableFeatures;
 use syntax::symbol::Symbol;
 use syntax_pos::DUMMY_SP;
-use arena::DroplessArena;
 
 use rustc::hir;
 
@@ -131,8 +130,7 @@ fn test_env<F>(source_string: &str,
             .expect("phase 2 aborted")
     };
 
-    let arena = DroplessArena::new();
-    let arenas = ty::GlobalArenas::new();
+    let arenas = ty::AllArenas::new();
     let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
 
     // run just enough stuff to build a tcx:
@@ -149,7 +147,6 @@ fn test_env<F>(source_string: &str,
                              ty::maps::Providers::default(),
                              ty::maps::Providers::default(),
                              &arenas,
-                             &arena,
                              resolutions,
                              hir_map,
                              OnDiskCache::new_empty(sess.codemap()),
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 840346c447b..2ac49958d3c 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -42,6 +42,8 @@ use std::cell::{RefCell, Cell};
 use std::mem;
 use std::rc::Rc;
 use std::{error, fmt};
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering::SeqCst;
 
 mod diagnostic;
 mod diagnostic_builder;
@@ -236,7 +238,7 @@ pub use diagnostic_builder::DiagnosticBuilder;
 pub struct Handler {
     pub flags: HandlerFlags,
 
-    err_count: Cell<usize>,
+    err_count: AtomicUsize,
     emitter: RefCell<Box<Emitter>>,
     continue_after_error: Cell<bool>,
     delayed_span_bug: RefCell<Option<Diagnostic>>,
@@ -295,7 +297,7 @@ impl Handler {
     pub fn with_emitter_and_flags(e: Box<Emitter>, flags: HandlerFlags) -> Handler {
         Handler {
             flags,
-            err_count: Cell::new(0),
+            err_count: AtomicUsize::new(0),
             emitter: RefCell::new(e),
             continue_after_error: Cell::new(true),
             delayed_span_bug: RefCell::new(None),
@@ -311,7 +313,7 @@ impl Handler {
     // NOTE: DO NOT call this function from rustc, as it relies on `err_count` being non-zero
     // if an error happened to avoid ICEs. This function should only be called from tools.
     pub fn reset_err_count(&self) {
-        self.err_count.set(0);
+        self.err_count.store(0, SeqCst);
     }
 
     pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> {
@@ -507,19 +509,19 @@ impl Handler {
 
     fn bump_err_count(&self) {
         self.panic_if_treat_err_as_bug();
-        self.err_count.set(self.err_count.get() + 1);
+        self.err_count.fetch_add(1, SeqCst);
     }
 
     pub fn err_count(&self) -> usize {
-        self.err_count.get()
+        self.err_count.load(SeqCst)
     }
 
     pub fn has_errors(&self) -> bool {
-        self.err_count.get() > 0
+        self.err_count() > 0
     }
     pub fn abort_if_errors(&self) {
         let s;
-        match self.err_count.get() {
+        match self.err_count() {
             0 => {
                 if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
                     DiagnosticBuilder::new_diagnostic(self, bug).emit();
@@ -528,7 +530,7 @@ impl Handler {
             }
             1 => s = "aborting due to previous error".to_string(),
             _ => {
-                s = format!("aborting due to {} previous errors", self.err_count.get());
+                s = format!("aborting due to {} previous errors", self.err_count());
             }
         }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 456a00947ae..b353c0da865 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -14,7 +14,7 @@ use rustc::session::{self, config};
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
 use rustc::middle::privacy::AccessLevels;
-use rustc::ty::{self, TyCtxt, GlobalArenas};
+use rustc::ty::{self, TyCtxt, AllArenas};
 use rustc::hir::map as hir_map;
 use rustc::lint;
 use rustc::util::nodemap::FxHashMap;
@@ -37,7 +37,6 @@ use visit_ast::RustdocVisitor;
 use clean;
 use clean::Clean;
 use html::render::RenderInfo;
-use arena::DroplessArena;
 
 pub use rustc::session::config::Input;
 pub use rustc::session::search_paths::SearchPaths;
@@ -170,8 +169,7 @@ pub fn run_core(search_paths: SearchPaths,
         abort_on_err(result, &sess)
     };
 
-    let arena = DroplessArena::new();
-    let arenas = GlobalArenas::new();
+    let arenas = AllArenas::new();
     let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
     let output_filenames = driver::build_output_filenames(&input,
                                                           &None,
@@ -185,7 +183,6 @@ pub fn run_core(search_paths: SearchPaths,
                                                      hir_map,
                                                      analysis,
                                                      resolutions,
-                                                     &arena,
                                                      &arenas,
                                                      &name,
                                                      &output_filenames,
diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs
index d8ae9729224..de7eebe7bf3 100644
--- a/src/libserialize/collection_impls.rs
+++ b/src/libserialize/collection_impls.rs
@@ -15,6 +15,7 @@ use std::hash::{Hash, BuildHasher};
 use {Decodable, Encodable, Decoder, Encoder};
 use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet};
 use std::rc::Rc;
+use std::sync::Arc;
 
 impl<
     T: Encodable
@@ -218,3 +219,26 @@ impl<T: Decodable> Decodable for Rc<[T]> {
         })
     }
 }
+
+impl<T: Encodable> Encodable for Arc<[T]> {
+    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+        s.emit_seq(self.len(), |s| {
+            for (index, e) in self.iter().enumerate() {
+                s.emit_seq_elt(index, |s| e.encode(s))?;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<T: Decodable> Decodable for Arc<[T]> {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Arc<[T]>, D::Error> {
+        d.read_seq(|d, len| {
+            let mut vec = Vec::with_capacity(len);
+            for index in 0..len {
+                vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
+            }
+            Ok(vec.into())
+        })
+    }
+}
\ No newline at end of file
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index e5e95002e10..cc72ff7d15d 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -31,7 +31,7 @@ use symbol::Symbol;
 use tokenstream::{TokenStream, TokenTree, Delimited};
 use util::ThinVec;
 
-use std::cell::{RefCell, Cell};
+use std::cell::RefCell;
 use std::iter;
 
 thread_local! {
@@ -419,16 +419,14 @@ pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem {
     MetaItem { span: sp, name: name, node: MetaItemKind::Word }
 }
 
+pub fn mk_attr_id() -> AttrId {
+    use std::sync::atomic::AtomicUsize;
+    use std::sync::atomic::Ordering;
 
+    static NEXT_ATTR_ID: AtomicUsize = AtomicUsize::new(0);
 
-thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) }
-
-pub fn mk_attr_id() -> AttrId {
-    let id = NEXT_ATTR_ID.with(|slot| {
-        let r = slot.get();
-        slot.set(r + 1);
-        r
-    });
+    let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
+    assert!(id != ::std::usize::MAX);
     AttrId(id)
 }
 
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 44383233a8a..0b51f2e9814 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -24,6 +24,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(match_default_bindings)]
 #![feature(i128_type)]
+#![feature(const_atomic_usize_new)]
 
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]