diff --git a/src/Cargo.lock b/src/Cargo.lock index 4364d7001cdfe..4cb82f94251ff 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1844,6 +1844,27 @@ dependencies = [ "rustc_target 0.0.0", ] +[[package]] +name = "rustc-rayon" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-rayon-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -1911,6 +1932,7 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "serialize 0.0.0", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1926,6 +1948,7 @@ dependencies = [ "graphviz 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_borrowck 0.0.0", "rustc_data_structures 0.0.0", @@ -1943,6 +1966,7 @@ dependencies = [ "rustc_traits 0.0.0", "rustc_trans_utils 0.0.0", "rustc_typeck 0.0.0", + "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "syntax 0.0.0", "syntax_ext 0.0.0", @@ -3118,6 +3142,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50671adb9b0a7c57a4690ac6a40cb614879f543b64aada42f55b66212492323" "checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" +"checksum rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1aa5cd8c3a706edb19b6ec6aa7b056bdc635b6e99c5cf7014f9af9d92f15e99" +"checksum rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d69983f8613a9c3ba1a3bbf5e8bdf2fd5c42317b1d8dd8623ca8030173bf8a6b" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a" "checksum rustfix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "165a212dd11124d7070892da20f71d82970ef1d1dd41cd804b70f39740a21c85" diff --git a/src/librustc/hir/itemlikevisit.rs b/src/librustc/hir/itemlikevisit.rs index 2221ecf07b434..a62000e10c79f 100644 --- a/src/librustc/hir/itemlikevisit.rs +++ b/src/librustc/hir/itemlikevisit.rs @@ -88,3 +88,33 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> self.visitor.visit_impl_item(impl_item); } } + +/// A parallel variant of ItemLikeVisitor +pub trait ParItemLikeVisitor<'hir> { + fn visit_item(&self, item: &'hir Item); + fn visit_trait_item(&self, trait_item: &'hir TraitItem); + fn visit_impl_item(&self, impl_item: &'hir ImplItem); +} + +pub trait IntoVisitor<'hir> { + type Visitor: Visitor<'hir>; + fn into_visitor(&self) -> Self::Visitor; +} + +pub struct ParDeepVisitor(pub V); + +impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor + where V: IntoVisitor<'hir> +{ + fn visit_item(&self, item: &'hir Item) { + self.0.into_visitor().visit_item(item); + } + + fn visit_trait_item(&self, trait_item: &'hir TraitItem) { + self.0.into_visitor().visit_trait_item(trait_item); + } + + fn visit_impl_item(&self, impl_item: &'hir ImplItem) { + self.0.into_visitor().visit_impl_item(impl_item); + } +} diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 0dc89d64bd501..33076267dbc9d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -48,6 +48,7 @@ use ty::AdtKind; use ty::maps::Providers; use rustc_data_structures::indexed_vec; +use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope}; use serialize::{self, Encoder, Encodable, Decoder, Decodable}; use std::collections::BTreeMap; @@ -720,6 +721,31 @@ impl Crate { } } + /// A parallel version of visit_all_item_likes + pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V) + where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send + { + scope(|s| { + s.spawn(|_| { + par_iter(&self.items).for_each(|(_, item)| { + visitor.visit_item(item); + }); + }); + + s.spawn(|_| { + par_iter(&self.trait_items).for_each(|(_, trait_item)| { + visitor.visit_trait_item(trait_item); + }); + }); + + s.spawn(|_| { + par_iter(&self.impl_items).for_each(|(_, impl_item)| { + visitor.visit_impl_item(impl_item); + }); + }); + }); + } + pub fn body(&self, id: BodyId) -> &Body { &self.bodies[&id] } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 4400ebc294fd8..61c8470b616f8 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -38,7 +38,7 @@ use syntax::ext::base::SyntaxExtension; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_target::spec::Target; -use rustc_data_structures::sync::{MetadataRef, Lrc}; +use rustc_data_structures::sync::{self, MetadataRef, Lrc}; pub use self::NativeLibraryKind::*; @@ -255,6 +255,8 @@ pub trait CrateStore { fn metadata_encoding_version(&self) -> &[u8]; } +pub type CrateStoreDyn = CrateStore + sync::Sync; + // FIXME: find a better place for this? pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { let mut err_count = 0; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 23f84881c7980..bbf873290a928 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -869,10 +869,16 @@ impl Session { ret } + /// Returns the number of query threads that should be used for this + /// compilation + pub fn query_threads_from_opts(opts: &config::Options) -> usize { + opts.debugging_opts.query_threads.unwrap_or(1) + } + /// 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) + Self::query_threads_from_opts(&self.opts) } /// Returns the number of codegen units that should be used for this diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f224f87da0a05..dcd20465fbb9a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -26,7 +26,7 @@ use lint::{self, Lint}; use ich::{StableHashingContext, NodeIdHashingMode}; use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use infer::outlives::free_region_map::FreeRegionMap; -use middle::cstore::{CrateStore, LinkMeta}; +use middle::cstore::{CrateStoreDyn, LinkMeta}; use middle::cstore::EncodedMetadata; use middle::lang_items; use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; @@ -852,7 +852,7 @@ pub struct GlobalCtxt<'tcx> { global_arenas: &'tcx GlobalArenas<'tcx>, global_interners: CtxtInterners<'tcx>, - cstore: &'tcx dyn CrateStore, + cstore: &'tcx CrateStoreDyn, pub sess: &'tcx Session, @@ -1188,7 +1188,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// value (types, substs, etc.) can only be used while `ty::tls` has a valid /// reference to the context, to allow formatting values that need it. pub fn create_and_enter(s: &'tcx Session, - cstore: &'tcx dyn CrateStore, + cstore: &'tcx CrateStoreDyn, local_providers: ty::maps::Providers<'tcx>, extern_providers: ty::maps::Providers<'tcx>, arenas: &'tcx AllArenas<'tcx>, @@ -1800,9 +1800,11 @@ pub mod tls { /// in librustc otherwise. It is used to when diagnostic messages are /// emitted and stores them in the current query, if there is one. fn track_diagnostic(diagnostic: &Diagnostic) { - with_context(|context| { - if let Some(ref query) = context.query { - query.diagnostics.lock().push(diagnostic.clone()); + with_context_opt(|icx| { + if let Some(icx) = icx { + if let Some(ref query) = icx.query { + query.diagnostics.lock().push(diagnostic.clone()); + } } }) } diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 9178d0d00faa4..6f1cbcad2f46c 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -16,6 +16,7 @@ serialize = { path = "../libserialize" } cfg-if = "0.1.2" stable_deref_trait = "1.0.0" parking_lot_core = "0.2.8" +rustc-rayon = "0.1.0" [dependencies.parking_lot] version = "0.5" diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 597d1627ada03..b2e7450e76cdf 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -44,6 +44,7 @@ extern crate parking_lot; #[macro_use] extern crate cfg_if; extern crate stable_deref_trait; +extern crate rustc_rayon as rayon; // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 3b7d6efbdae1e..3661763133014 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! This mdoule defines types which are thread safe if cfg!(parallel_queries) is true. +//! This module defines types which are thread safe if cfg!(parallel_queries) is true. //! //! `Lrc` is an alias of either Rc or Arc. //! @@ -40,6 +40,29 @@ use std; use std::ops::{Deref, DerefMut}; use owning_ref::{Erased, OwningRef}; +pub fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) + where A: FnOnce() -> RA, + B: FnOnce() -> RB +{ + (oper_a(), oper_b()) +} + +pub struct SerialScope; + +impl SerialScope { + pub fn spawn(&self, f: F) + where F: FnOnce(&SerialScope) + { + f(self) + } +} + +pub fn serial_scope(f: F) -> R + where F: FnOnce(&SerialScope) -> R +{ + f(&SerialScope) +} + cfg_if! { if #[cfg(not(parallel_queries))] { pub auto trait Send {} @@ -55,9 +78,19 @@ cfg_if! { } } + pub use self::serial_join as join; + pub use self::serial_scope as scope; + + pub use std::iter::Iterator as ParallelIterator; + + pub fn par_iter(t: T) -> T::IntoIter { + t.into_iter() + } + pub type MetadataRef = OwningRef, [u8]>; pub use std::rc::Rc as Lrc; + pub use std::rc::Weak as Weak; pub use std::cell::Ref as ReadGuard; pub use std::cell::RefMut as WriteGuard; pub use std::cell::RefMut as LockGuard; @@ -160,6 +193,7 @@ cfg_if! { pub use parking_lot::MutexGuard as LockGuard; pub use std::sync::Arc as Lrc; + pub use std::sync::Weak as Weak; pub use self::Lock as MTLock; @@ -167,6 +201,14 @@ cfg_if! { use parking_lot::RwLock as InnerRwLock; use std::thread; + pub use rayon::{join, scope}; + + pub use rayon::iter::ParallelIterator; + use rayon::iter::IntoParallelIterator; + + pub fn par_iter(t: T) -> T::Iter { + t.into_par_iter() + } pub type MetadataRef = OwningRef, [u8]>; diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 5aae1bcad896f..1827533f0acb5 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -13,6 +13,8 @@ arena = { path = "../libarena" } graphviz = { path = "../libgraphviz" } log = "0.4" env_logger = { version = "0.5", default-features = false } +rustc-rayon = "0.1.0" +scoped-tls = { version = "0.1.1", features = ["nightly"] } rustc = { path = "../librustc" } rustc_allocator = { path = "../librustc_allocator" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1e74039503d51..62b3accc46f18 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -20,7 +20,7 @@ use rustc::session::config::{self, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; -use rustc::middle::cstore::CrateStore; +use rustc::middle::cstore::CrateStoreDyn; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, AllArenas, Resolutions, TyCtxt}; use rustc::traits; @@ -49,7 +49,7 @@ use std::fs; use std::io::{self, Write}; use std::iter; use std::path::{Path, PathBuf}; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use std::sync::mpsc; use syntax::{self, ast, attr, diagnostics, visit}; use syntax::ext::base::ExtCtxt; @@ -64,6 +64,51 @@ use pretty::ReplaceBodyWithLoop; use profile; +#[cfg(not(parallel_queries))] +pub fn spawn_thread_pool R + sync::Send, R: sync::Send>( + opts: config::Options, + f: F +) -> R { + f(opts) +} + +#[cfg(parallel_queries)] +pub fn spawn_thread_pool R + sync::Send, R: sync::Send>( + opts: config::Options, + f: F +) -> R { + use syntax; + use syntax_pos; + use rayon::{ThreadPoolBuilder, ThreadPool}; + + let config = ThreadPoolBuilder::new().num_threads(Session::query_threads_from_opts(&opts)) + .stack_size(16 * 1024 * 1024); + + let with_pool = move |pool: &ThreadPool| { + pool.install(move || f(opts)) + }; + + syntax::GLOBALS.with(|syntax_globals| { + syntax_pos::GLOBALS.with(|syntax_pos_globals| { + // The main handler run for each Rayon worker thread and sets up + // the thread local rustc uses. syntax_globals and syntax_pos_globals are + // captured and set on the new threads. ty::tls::with_thread_locals sets up + // thread local callbacks from libsyntax + let main_handler = move |worker: &mut FnMut()| { + syntax::GLOBALS.set(syntax_globals, || { + syntax_pos::GLOBALS.set(syntax_pos_globals, || { + ty::tls::with_thread_locals(|| { + worker() + }) + }) + }) + }; + + ThreadPool::scoped_pool(config, main_handler, with_pool).unwrap() + }) + }) +} + pub fn compile_input( trans: Box, sess: &Session, @@ -1047,7 +1092,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>( trans: &TransCrate, control: &CompileController, sess: &'tcx Session, - cstore: &'tcx CrateStore, + cstore: &'tcx CrateStoreDyn, hir_map: hir_map::Map<'tcx>, mut analysis: ty::CrateAnalysis, resolutions: Resolutions, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index a1052ca6c3ca9..148fbd73e9bd8 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -27,12 +27,15 @@ #![feature(rustc_stack_internals)] #![feature(no_debug)] +#![recursion_limit="256"] + extern crate arena; extern crate getopts; extern crate graphviz; extern crate env_logger; #[cfg(unix)] extern crate libc; +extern crate rustc_rayon as rayon; extern crate rustc; extern crate rustc_allocator; extern crate rustc_target; @@ -51,6 +54,7 @@ extern crate rustc_save_analysis; extern crate rustc_traits; extern crate rustc_trans_utils; extern crate rustc_typeck; +extern crate scoped_tls; extern crate serialize; #[macro_use] extern crate log; @@ -64,7 +68,7 @@ use pretty::{PpMode, UserIdentifiedItem}; use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use rustc_data_structures::OnDrop; use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::CompileIncomplete; @@ -448,22 +452,33 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box { // See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. pub fn run_compiler<'a>(args: &[String], - callbacks: &mut CompilerCalls<'a>, + callbacks: &mut (CompilerCalls<'a> + sync::Send), file_loader: Option>, emitter_dest: Option>) -> (CompileResult, Option) { syntax::with_globals(|| { - run_compiler_impl(args, callbacks, file_loader, emitter_dest) + let matches = match handle_options(args) { + Some(matches) => matches, + None => return (Ok(()), None), + }; + + let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); + + driver::spawn_thread_pool(sopts, |sopts| { + run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest) + }) }) } -fn run_compiler_impl<'a>(args: &[String], - callbacks: &mut CompilerCalls<'a>, - file_loader: Option>, - emitter_dest: Option>) - -> (CompileResult, Option) -{ +fn run_compiler_with_pool<'a>( + matches: getopts::Matches, + sopts: config::Options, + cfg: ast::CrateConfig, + callbacks: &mut (CompilerCalls<'a> + sync::Send), + file_loader: Option>, + emitter_dest: Option> +) -> (CompileResult, Option) { macro_rules! do_or_return {($expr: expr, $sess: expr) => { match $expr { Compilation::Stop => return (Ok(()), $sess), @@ -471,13 +486,6 @@ fn run_compiler_impl<'a>(args: &[String], } }} - let matches = match handle_options(args) { - Some(matches) => matches, - None => return (Ok(()), None), - }; - - let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); - let descriptions = diagnostics_registry(); do_or_return!(callbacks.early_callback(&matches, diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 70b73ebb8cdeb..108b47623383c 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -20,7 +20,7 @@ use {abort_on_err, driver}; use rustc::ty::{self, TyCtxt, Resolutions, AllArenas}; use rustc::cfg; use rustc::cfg::graphviz::LabelledCFG; -use rustc::middle::cstore::CrateStore; +use rustc::middle::cstore::CrateStoreDyn; use rustc::session::Session; use rustc::session::config::{Input, OutputFilenames}; use rustc_borrowck as borrowck; @@ -199,7 +199,7 @@ impl PpSourceMode { } fn call_with_pp_support_hir<'tcx, A, F>(&self, sess: &'tcx Session, - cstore: &'tcx CrateStore, + cstore: &'tcx CrateStoreDyn, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, @@ -912,7 +912,7 @@ pub fn print_after_parsing(sess: &Session, } pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, - cstore: &'tcx CrateStore, + cstore: &'tcx CrateStoreDyn, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, @@ -1068,7 +1068,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, // with a different callback than the standard driver, so that isn't easy. // Instead, we call that function ourselves. fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, - cstore: &'a CrateStore, + cstore: &'a CrateStoreDyn, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index d2ee3d8743c2c..7ae26e9e9798e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -99,20 +99,25 @@ fn test_env(source_string: &str, where F: FnOnce(Env) { syntax::with_globals(|| { - test_env_impl(source_string, args, body) + let mut options = config::basic_options(); + options.debugging_opts.verbose = true; + options.unstable_features = UnstableFeatures::Allow; + + driver::spawn_thread_pool(options, |options| { + test_env_with_pool(options, source_string, args, body) + }) }); } -fn test_env_impl(source_string: &str, - (emitter, expected_err_count): (Box, usize), - body: F) +fn test_env_with_pool( + options: config::Options, + source_string: &str, + (emitter, expected_err_count): (Box, usize), + body: F +) where F: FnOnce(Env) { - let mut options = config::basic_options(); - options.debugging_opts.verbose = true; - options.unstable_features = UnstableFeatures::Allow; let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter); - let sess = session::build_session_(options, None, diagnostic_handler, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3ffdd5595a2d5..7d3ba79282938 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -697,7 +697,7 @@ impl<'a> FromIterator<&'a DocFragment> for String { pub struct Attributes { pub doc_strings: Vec, pub other_attrs: Vec, - pub cfg: Option>, + pub cfg: Option>, pub span: Option, /// map from Rust paths to resolved defs and potential URL fragments pub links: Vec<(String, Option, Option)>, @@ -848,7 +848,7 @@ impl Attributes { Attributes { doc_strings, other_attrs, - cfg: if cfg == Cfg::True { None } else { Some(Rc::new(cfg)) }, + cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) }, span: sp, links: vec![], } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 61fb0b40c2315..6222edd5450f0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -161,161 +161,162 @@ pub fn run_core(search_paths: SearchPaths, edition, ..config::basic_options().clone() }; - - let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())); - let emitter: Box = match error_format { - ErrorOutputType::HumanReadable(color_config) => Box::new( - EmitterWriter::stderr( - color_config, - Some(codemap.clone()), - false, - sessopts.debugging_opts.teach, - ).ui_testing(sessopts.debugging_opts.ui_testing) - ), - ErrorOutputType::Json(pretty) => Box::new( - JsonEmitter::stderr( - None, - codemap.clone(), - pretty, - sessopts.debugging_opts.suggestion_applicability, - ).ui_testing(sessopts.debugging_opts.ui_testing) - ), - ErrorOutputType::Short(color_config) => Box::new( - EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false) - ), - }; - - let diagnostic_handler = errors::Handler::with_emitter_and_flags( - emitter, - errors::HandlerFlags { - can_emit_warnings: true, - treat_err_as_bug: false, - external_macro_backtrace: false, - ..Default::default() - }, - ); - - let mut sess = session::build_session_( - sessopts, cpath, diagnostic_handler, codemap, - ); - let trans = rustc_driver::get_trans(&sess); - let cstore = Rc::new(CStore::new(trans.metadata_loader())); - rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); - - let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs)); - target_features::add_configuration(&mut cfg, &sess, &*trans); - sess.parse_sess.config = cfg; - - let control = &driver::CompileController::basic(); - - let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input)); - - let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input); - - let mut crate_loader = CrateLoader::new(&sess, &cstore, &name); - - let resolver_arenas = resolve::Resolver::arenas(); - let result = driver::phase_2_configure_and_expand_inner(&sess, - &cstore, - krate, - None, - &name, - None, - resolve::MakeGlobMap::No, - &resolver_arenas, - &mut crate_loader, - |_| Ok(())); - let driver::InnerExpansionResult { - mut hir_forest, - resolver, - .. - } = abort_on_err(result, &sess); - - // We need to hold on to the complete resolver, so we clone everything - // for the analysis passes to use. Suboptimal, but necessary in the - // current architecture. - let defs = resolver.definitions.clone(); - let resolutions = ty::Resolutions { - freevars: resolver.freevars.clone(), - export_map: resolver.export_map.clone(), - trait_map: resolver.trait_map.clone(), - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(), - maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(), - }; - let analysis = ty::CrateAnalysis { - access_levels: Lrc::new(AccessLevels::default()), - name: name.to_string(), - glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None }, - }; - - 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, - &None, - &[], - &sess); - - let resolver = RefCell::new(resolver); - - abort_on_err(driver::phase_3_run_analysis_passes(&*trans, - control, - &sess, - &*cstore, - hir_map, - analysis, - resolutions, - &arenas, - &name, - &output_filenames, - |tcx, analysis, _, result| { - if let Err(_) = result { - sess.fatal("Compilation failed, aborting rustdoc"); - } - - let ty::CrateAnalysis { access_levels, .. } = analysis; - - // Convert from a NodeId set to a DefId set since we don't always have easy access - // to the map from defid -> nodeid - let access_levels = AccessLevels { - map: access_levels.map.iter() - .map(|(&k, &v)| (tcx.hir.local_def_id(k), v)) - .collect() + driver::spawn_thread_pool(sessopts, move |sessopts| { + let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())); + let emitter: Box = match error_format { + ErrorOutputType::HumanReadable(color_config) => Box::new( + EmitterWriter::stderr( + color_config, + Some(codemap.clone()), + false, + sessopts.debugging_opts.teach, + ).ui_testing(sessopts.debugging_opts.ui_testing) + ), + ErrorOutputType::Json(pretty) => Box::new( + JsonEmitter::stderr( + None, + codemap.clone(), + pretty, + sessopts.debugging_opts.suggestion_applicability, + ).ui_testing(sessopts.debugging_opts.ui_testing) + ), + ErrorOutputType::Short(color_config) => Box::new( + EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false) + ), }; - let send_trait = if crate_name == Some("core".to_string()) { - clean::get_trait_def_id(&tcx, &["marker", "Send"], true) - } else { - clean::get_trait_def_id(&tcx, &["core", "marker", "Send"], false) + let diagnostic_handler = errors::Handler::with_emitter_and_flags( + emitter, + errors::HandlerFlags { + can_emit_warnings: true, + treat_err_as_bug: false, + external_macro_backtrace: false, + ..Default::default() + }, + ); + + let mut sess = session::build_session_( + sessopts, cpath, diagnostic_handler, codemap, + ); + let trans = rustc_driver::get_trans(&sess); + let cstore = Rc::new(CStore::new(trans.metadata_loader())); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); + + let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs)); + target_features::add_configuration(&mut cfg, &sess, &*trans); + sess.parse_sess.config = cfg; + + let control = &driver::CompileController::basic(); + + let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input)); + + let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input); + + let mut crate_loader = CrateLoader::new(&sess, &cstore, &name); + + let resolver_arenas = resolve::Resolver::arenas(); + let result = driver::phase_2_configure_and_expand_inner(&sess, + &cstore, + krate, + None, + &name, + None, + resolve::MakeGlobMap::No, + &resolver_arenas, + &mut crate_loader, + |_| Ok(())); + let driver::InnerExpansionResult { + mut hir_forest, + resolver, + .. + } = abort_on_err(result, &sess); + + // We need to hold on to the complete resolver, so we clone everything + // for the analysis passes to use. Suboptimal, but necessary in the + // current architecture. + let defs = resolver.definitions.clone(); + let resolutions = ty::Resolutions { + freevars: resolver.freevars.clone(), + export_map: resolver.export_map.clone(), + trait_map: resolver.trait_map.clone(), + maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(), + maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(), }; - - let ctxt = DocContext { - tcx, - resolver: &resolver, - crate_name, - cstore: cstore.clone(), - populated_all_crate_impls: Cell::new(false), - access_levels: RefCell::new(access_levels), - external_traits: Default::default(), - active_extern_traits: Default::default(), - renderinfo: Default::default(), - ty_substs: Default::default(), - lt_substs: Default::default(), - impl_trait_bounds: Default::default(), - mod_ids: Default::default(), - send_trait: send_trait, - fake_def_ids: RefCell::new(FxHashMap()), - all_fake_def_ids: RefCell::new(FxHashSet()), - generated_synthetics: RefCell::new(FxHashSet()), - }; - debug!("crate: {:?}", tcx.hir.krate()); - - let krate = { - let mut v = RustdocVisitor::new(&*cstore, &ctxt); - v.visit(tcx.hir.krate()); - v.clean(&ctxt) + let analysis = ty::CrateAnalysis { + access_levels: Lrc::new(AccessLevels::default()), + name: name.to_string(), + glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None }, }; - (krate, ctxt.renderinfo.into_inner()) - }), &sess) + 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, + &None, + &[], + &sess); + + let resolver = RefCell::new(resolver); + + abort_on_err(driver::phase_3_run_analysis_passes(&*trans, + control, + &sess, + &*cstore, + hir_map, + analysis, + resolutions, + &arenas, + &name, + &output_filenames, + |tcx, analysis, _, result| { + if let Err(_) = result { + sess.fatal("Compilation failed, aborting rustdoc"); + } + + let ty::CrateAnalysis { access_levels, .. } = analysis; + + // Convert from a NodeId set to a DefId set since we don't always have easy access + // to the map from defid -> nodeid + let access_levels = AccessLevels { + map: access_levels.map.iter() + .map(|(&k, &v)| (tcx.hir.local_def_id(k), v)) + .collect() + }; + + let send_trait = if crate_name == Some("core".to_string()) { + clean::get_trait_def_id(&tcx, &["marker", "Send"], true) + } else { + clean::get_trait_def_id(&tcx, &["core", "marker", "Send"], false) + }; + + let ctxt = DocContext { + tcx, + resolver: &resolver, + crate_name, + cstore: cstore.clone(), + populated_all_crate_impls: Cell::new(false), + access_levels: RefCell::new(access_levels), + external_traits: Default::default(), + active_extern_traits: Default::default(), + renderinfo: Default::default(), + ty_substs: Default::default(), + lt_substs: Default::default(), + impl_trait_bounds: Default::default(), + mod_ids: Default::default(), + send_trait: send_trait, + fake_def_ids: RefCell::new(FxHashMap()), + all_fake_def_ids: RefCell::new(FxHashSet()), + generated_synthetics: RefCell::new(FxHashSet()), + }; + debug!("crate: {:?}", tcx.hir.krate()); + + let krate = { + let mut v = RustdocVisitor::new(&*cstore, &ctxt); + v.visit(tcx.hir.krate()); + v.clean(&ctxt) + }; + + (krate, ctxt.renderinfo.into_inner()) + }), &sess) + }) } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 059d41698953d..f2da09e16036e 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -26,6 +26,8 @@ #![feature(vec_remove_item)] #![feature(entry_and_modify)] +#![recursion_limit="256"] + extern crate arena; extern crate getopts; extern crate env_logger; diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 9e65fff5e2ac6..fc8abafd4d89b 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::rc::Rc; +use std::sync::Arc; use clean::{Crate, Item}; use clean::cfg::Cfg; @@ -20,7 +20,7 @@ pub fn propagate_doc_cfg(cr: Crate) -> PluginResult { } struct CfgPropagator { - parent_cfg: Option>, + parent_cfg: Option>, } impl DocFolder for CfgPropagator { @@ -31,8 +31,8 @@ impl DocFolder for CfgPropagator { (None, None) => None, (Some(rc), None) | (None, Some(rc)) => Some(rc), (Some(mut a), Some(b)) => { - let b = Rc::try_unwrap(b).unwrap_or_else(|rc| Cfg::clone(&rc)); - *Rc::make_mut(&mut a) &= b; + let b = Arc::try_unwrap(b).unwrap_or_else(|rc| Cfg::clone(&rc)); + *Arc::make_mut(&mut a) &= b; Some(a) } }; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index c4eaa48e49db6..7be7ce313fcff 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -85,77 +85,80 @@ pub fn run(input_path: &Path, edition, ..config::basic_options().clone() }; - - let codemap = Lrc::new(CodeMap::new(sessopts.file_path_mapping())); - let handler = - errors::Handler::with_tty_emitter(ColorConfig::Auto, - true, false, - Some(codemap.clone())); - - let mut sess = session::build_session_( - sessopts, Some(input_path.to_owned()), handler, codemap.clone(), - ); - let trans = rustc_driver::get_trans(&sess); - let cstore = CStore::new(trans.metadata_loader()); - rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); - - let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); - target_features::add_configuration(&mut cfg, &sess, &*trans); - sess.parse_sess.config = cfg; - - let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(), - &sess, - &input)); - let driver::ExpansionResult { defs, mut hir_forest, .. } = { - phase_2_configure_and_expand( - &sess, - &cstore, - krate, - None, - "rustdoc-test", - None, - MakeGlobMap::No, - |_| Ok(()), - ).expect("phase_2_configure_and_expand aborted in rustdoc!") - }; - - let crate_name = crate_name.unwrap_or_else(|| { - ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input) - }); - let mut opts = scrape_test_config(hir_forest.krate()); - opts.display_warnings |= display_warnings; - let mut collector = Collector::new(crate_name, - cfgs, - libs, - cg, - externs, - false, - opts, - maybe_sysroot, - Some(codemap), - None, - linker, - edition); - - { - let map = hir::map::map_crate(&sess, &cstore, &mut hir_forest, &defs); - let krate = map.krate(); - let mut hir_collector = HirCollector { - sess: &sess, - collector: &mut collector, - map: &map + driver::spawn_thread_pool(sessopts, |sessopts| { + let codemap = Lrc::new(CodeMap::new(sessopts.file_path_mapping())); + let handler = + errors::Handler::with_tty_emitter(ColorConfig::Auto, + true, false, + Some(codemap.clone())); + + let mut sess = session::build_session_( + sessopts, Some(input_path.to_owned()), handler, codemap.clone(), + ); + let trans = rustc_driver::get_trans(&sess); + let cstore = CStore::new(trans.metadata_loader()); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); + + let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone())); + target_features::add_configuration(&mut cfg, &sess, &*trans); + sess.parse_sess.config = cfg; + + let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(), + &sess, + &input)); + let driver::ExpansionResult { defs, mut hir_forest, .. } = { + phase_2_configure_and_expand( + &sess, + &cstore, + krate, + None, + "rustdoc-test", + None, + MakeGlobMap::No, + |_| Ok(()), + ).expect("phase_2_configure_and_expand aborted in rustdoc!") }; - hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { - intravisit::walk_crate(this, krate); + + let crate_name = crate_name.unwrap_or_else(|| { + ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input) }); - } + let mut opts = scrape_test_config(hir_forest.krate()); + opts.display_warnings |= display_warnings; + let mut collector = Collector::new( + crate_name, + cfgs, + libs, + cg, + externs, + false, + opts, + maybe_sysroot, + Some(codemap), + None, + linker, + edition + ); + + { + let map = hir::map::map_crate(&sess, &cstore, &mut hir_forest, &defs); + let krate = map.krate(); + let mut hir_collector = HirCollector { + sess: &sess, + collector: &mut collector, + map: &map + }; + hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { + intravisit::walk_crate(this, krate); + }); + } - test_args.insert(0, "rustdoctest".to_string()); + test_args.insert(0, "rustdoctest".to_string()); - testing::test_main(&test_args, - collector.tests.into_iter().collect(), - testing::Options::new().display_output(display_warnings)); - 0 + testing::test_main(&test_args, + collector.tests.into_iter().collect(), + testing::Options::new().display_output(display_warnings)); + 0 + }) } // Look for #![doc(test(no_crate_inject))], used by crates in the std facade @@ -229,102 +232,106 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, ..config::basic_options().clone() }; - // Shuffle around a few input and output handles here. We're going to pass - // an explicit handle into rustc to collect output messages, but we also - // want to catch the error message that rustc prints when it fails. - // - // We take our thread-local stderr (likely set by the test runner) and replace - // it with a sink that is also passed to rustc itself. When this function - // returns the output of the sink is copied onto the output of our own thread. - // - // The basic idea is to not use a default Handler for rustc, and then also - // not print things by default to the actual stderr. - struct Sink(Arc>>); - impl Write for Sink { - fn write(&mut self, data: &[u8]) -> io::Result { - Write::write(&mut *self.0.lock().unwrap(), data) + let (libdir, outdir) = driver::spawn_thread_pool(sessopts, |sessopts| { + // Shuffle around a few input and output handles here. We're going to pass + // an explicit handle into rustc to collect output messages, but we also + // want to catch the error message that rustc prints when it fails. + // + // We take our thread-local stderr (likely set by the test runner) and replace + // it with a sink that is also passed to rustc itself. When this function + // returns the output of the sink is copied onto the output of our own thread. + // + // The basic idea is to not use a default Handler for rustc, and then also + // not print things by default to the actual stderr. + struct Sink(Arc>>); + impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } } - fn flush(&mut self) -> io::Result<()> { Ok(()) } - } - struct Bomb(Arc>>, Box); - impl Drop for Bomb { - fn drop(&mut self) { - let _ = self.1.write_all(&self.0.lock().unwrap()); + struct Bomb(Arc>>, Box); + impl Drop for Bomb { + fn drop(&mut self) { + let _ = self.1.write_all(&self.0.lock().unwrap()); + } } - } - let data = Arc::new(Mutex::new(Vec::new())); - let codemap = Lrc::new(CodeMap::new_doctest( - sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize - )); - let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), - Some(codemap.clone()), - false, - false); - let old = io::set_panic(Some(box Sink(data.clone()))); - let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout())); - - // Compile the code - let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter); - - let mut sess = session::build_session_( - sessopts, None, diagnostic_handler, codemap, - ); - let trans = rustc_driver::get_trans(&sess); - let cstore = CStore::new(trans.metadata_loader()); - rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); - - 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, config::parse_cfgspecs(cfgs.clone())); - target_features::add_configuration(&mut cfg, &sess, &*trans); - sess.parse_sess.config = cfg; - - let out = Some(outdir.lock().unwrap().path().to_path_buf()); - - if no_run { - control.after_analysis.stop = Compilation::Stop; - } - - let res = panic::catch_unwind(AssertUnwindSafe(|| { - driver::compile_input( - trans, - &sess, - &cstore, - &None, - &input, - &out, - &None, - None, - &control - ) - })); - - let compile_result = match res { - Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()), - Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(()) - }; - - match (compile_result, compile_fail) { - (Ok(()), true) => { - panic!("test compiled while it wasn't supposed to") + let data = Arc::new(Mutex::new(Vec::new())); + let codemap = Lrc::new(CodeMap::new_doctest( + sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize + )); + let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()), + Some(codemap.clone()), + false, + false); + let old = io::set_panic(Some(box Sink(data.clone()))); + let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout())); + + // Compile the code + let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter); + + let mut sess = session::build_session_( + sessopts, None, diagnostic_handler, codemap, + ); + let trans = rustc_driver::get_trans(&sess); + let cstore = CStore::new(trans.metadata_loader()); + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); + + 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, config::parse_cfgspecs(cfgs.clone())); + target_features::add_configuration(&mut cfg, &sess, &*trans); + sess.parse_sess.config = cfg; + + let out = Some(outdir.lock().unwrap().path().to_path_buf()); + + if no_run { + control.after_analysis.stop = Compilation::Stop; } - (Ok(()), false) => {} - (Err(()), true) => { - if error_codes.len() > 0 { - let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); - error_codes.retain(|err| !out.contains(err)); + + let res = panic::catch_unwind(AssertUnwindSafe(|| { + driver::compile_input( + trans, + &sess, + &cstore, + &None, + &input, + &out, + &None, + None, + &control + ) + })); + + let compile_result = match res { + Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()), + Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(()) + }; + + match (compile_result, compile_fail) { + (Ok(()), true) => { + panic!("test compiled while it wasn't supposed to") + } + (Ok(()), false) => {} + (Err(()), true) => { + if error_codes.len() > 0 { + let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap(); + error_codes.retain(|err| !out.contains(err)); + } + } + (Err(()), false) => { + panic!("couldn't compile the test") } } - (Err(()), false) => { - panic!("couldn't compile the test") + + if error_codes.len() > 0 { + panic!("Some expected error codes were not found: {:?}", error_codes); } - } - if error_codes.len() > 0 { - panic!("Some expected error codes were not found: {:?}", error_codes); - } + (libdir, outdir) + }); if no_run { return } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index f148aaf7267ee..90af3ba51ecad 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -73,7 +73,7 @@ macro_rules! unwrap_or { } } -struct Globals { +pub struct Globals { used_attrs: Lock>, known_attrs: Lock>, syntax_pos_globals: syntax_pos::Globals, @@ -98,7 +98,7 @@ pub fn with_globals(f: F) -> R }) } -scoped_thread_local!(static GLOBALS: Globals); +scoped_thread_local!(pub static GLOBALS: Globals); #[macro_use] pub mod diagnostics { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index b84ff5697a4c8..2258ed12779e4 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -527,7 +527,7 @@ impl PartialOrd for InternedString { if self.symbol == other.symbol { return Some(Ordering::Equal); } - self.with(|self_str| other.with(|other_str| self_str.partial_cmp(&other_str))) + self.with(|self_str| other.with(|other_str| self_str.partial_cmp(other_str))) } } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 9a87fcb00d526..c34cf1bd5ec09 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -59,6 +59,7 @@ static WHITELIST_CRATES: &'static [CrateVersion] = &[ static WHITELIST: &'static [Crate] = &[ Crate("aho-corasick"), Crate("ar"), + Crate("arrayvec"), Crate("atty"), Crate("backtrace"), Crate("backtrace-sys"), @@ -67,6 +68,10 @@ static WHITELIST: &'static [Crate] = &[ Crate("cc"), Crate("cfg-if"), Crate("cmake"), + Crate("crossbeam-deque"), + Crate("crossbeam-epoch"), + Crate("crossbeam-utils"), + Crate("either"), Crate("ena"), Crate("env_logger"), Crate("filetime"), @@ -82,7 +87,9 @@ static WHITELIST: &'static [Crate] = &[ Crate("log"), Crate("log_settings"), Crate("memchr"), + Crate("memoffset"), Crate("miniz-sys"), + Crate("nodrop"), Crate("num_cpus"), Crate("owning_ref"), Crate("parking_lot"), @@ -95,7 +102,10 @@ static WHITELIST: &'static [Crate] = &[ Crate("regex-syntax"), Crate("remove_dir_all"), Crate("rustc-demangle"), + Crate("rustc-rayon"), + Crate("rustc-rayon-core"), Crate("scoped-tls"), + Crate("scopeguard"), Crate("smallvec"), Crate("stable_deref_trait"), Crate("tempdir"),