From 9f82785c81c68d117617b6b45bce437649f94833 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 15 May 2020 21:43:06 -0700 Subject: [PATCH 1/4] Replace `rustc_data_structures::sync::Once` with `OnceCell` --- Cargo.lock | 1 + src/librustc_data_structures/Cargo.toml | 1 + src/librustc_data_structures/sync.rs | 133 +----------------------- src/tools/tidy/src/deps.rs | 1 + 4 files changed, 7 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d81fd6e8d3afd..ebcc11d2b26d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3791,6 +3791,7 @@ dependencies = [ "libc", "log", "measureme", + "once_cell", "parking_lot 0.10.2", "rustc-hash", "rustc-rayon", diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 81ad032967bfd..67721220526ca 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -15,6 +15,7 @@ indexmap = "1" log = "0.4" jobserver_crate = { version = "0.1.13", package = "jobserver" } lazy_static = "1" +once_cell = { version = "1", features = ["parking_lot"] } rustc_serialize = { path = "../libserialize", package = "serialize" } graphviz = { path = "../libgraphviz" } cfg-if = "0.1.2" diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 9051b1751b119..39afb3d82ff5a 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -20,7 +20,6 @@ use crate::owning_ref::{Erased, OwningRef}; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; -use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; pub use std::sync::atomic::Ordering; @@ -230,6 +229,8 @@ cfg_if! { pub use std::cell::RefMut as LockGuard; pub use std::cell::RefMut as MappedLockGuard; + pub use once_cell::unsync::OnceCell; + use std::cell::RefCell as InnerRwLock; use std::cell::RefCell as InnerLock; @@ -313,6 +314,8 @@ cfg_if! { pub use parking_lot::MutexGuard as LockGuard; pub use parking_lot::MappedMutexGuard as MappedLockGuard; + pub use once_cell::sync::OnceCell; + pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64}; pub use crossbeam_utils::atomic::AtomicCell; @@ -432,134 +435,6 @@ impl HashMapExt for HashMap } } -/// A type whose inner value can be written once and then will stay read-only -// This contains a PhantomData since this type conceptually owns a T outside the Mutex once -// initialized. This ensures that Once is Sync only if T is. If we did not have PhantomData -// we could send a &Once> to multiple threads and call `get` on it to get access -// to &Cell on those threads. -pub struct Once(Lock>, PhantomData); - -impl Once { - /// Creates an Once value which is uninitialized - #[inline(always)] - pub fn new() -> Self { - Once(Lock::new(None), PhantomData) - } - - /// Consumes the value and returns Some(T) if it was initialized - #[inline(always)] - pub fn into_inner(self) -> Option { - self.0.into_inner() - } - - /// Tries to initialize the inner value to `value`. - /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it - /// otherwise if the inner value was already set it returns `value` back to the caller - #[inline] - pub fn try_set(&self, value: T) -> Option { - let mut lock = self.0.lock(); - if lock.is_some() { - return Some(value); - } - *lock = Some(value); - None - } - - /// Tries to initialize the inner value to `value`. - /// Returns `None` if the inner value was uninitialized and `value` was consumed setting it - /// otherwise if the inner value was already set it asserts that `value` is equal to the inner - /// value and then returns `value` back to the caller - #[inline] - pub fn try_set_same(&self, value: T) -> Option - where - T: Eq, - { - let mut lock = self.0.lock(); - if let Some(ref inner) = *lock { - assert!(*inner == value); - return Some(value); - } - *lock = Some(value); - None - } - - /// Tries to initialize the inner value to `value` and panics if it was already initialized - #[inline] - pub fn set(&self, value: T) { - assert!(self.try_set(value).is_none()); - } - - /// Initializes the inner value if it wasn't already done by calling the provided closure. It - /// ensures that no-one else can access the value in the mean time by holding a lock for the - /// duration of the closure. - /// A reference to the inner value is returned. - #[inline] - pub fn init_locking T>(&self, f: F) -> &T { - { - let mut lock = self.0.lock(); - if lock.is_none() { - *lock = Some(f()); - } - } - - self.borrow() - } - - /// Tries to initialize the inner value by calling the closure without ensuring that no-one - /// else can access it. This mean when this is called from multiple threads, multiple - /// closures may concurrently be computing a value which the inner value should take. - /// Only one of these closures are used to actually initialize the value. - /// If some other closure already set the value, - /// we return the value our closure computed wrapped in a `Option`. - /// If our closure set the value, `None` is returned. - /// If the value is already initialized, the closure is not called and `None` is returned. - #[inline] - pub fn init_nonlocking T>(&self, f: F) -> Option { - if self.0.lock().is_some() { None } else { self.try_set(f()) } - } - - /// Tries to initialize the inner value by calling the closure without ensuring that no-one - /// else can access it. This mean when this is called from multiple threads, multiple - /// closures may concurrently be computing a value which the inner value should take. - /// Only one of these closures are used to actually initialize the value. - /// If some other closure already set the value, we assert that it our closure computed - /// a value equal to the value already set and then - /// we return the value our closure computed wrapped in a `Option`. - /// If our closure set the value, `None` is returned. - /// If the value is already initialized, the closure is not called and `None` is returned. - #[inline] - pub fn init_nonlocking_same T>(&self, f: F) -> Option - where - T: Eq, - { - if self.0.lock().is_some() { None } else { self.try_set_same(f()) } - } - - /// Tries to get a reference to the inner value, returns `None` if it is not yet initialized - #[inline(always)] - pub fn try_get(&self) -> Option<&T> { - let lock = &*self.0.lock(); - if let Some(ref inner) = *lock { - // This is safe since we won't mutate the inner value - unsafe { Some(&*(inner as *const T)) } - } else { - None - } - } - - /// Gets reference to the inner value, panics if it is not yet initialized - #[inline(always)] - pub fn get(&self) -> &T { - self.try_get().expect("value was not set") - } - - /// Gets reference to the inner value, panics if it is not yet initialized - #[inline(always)] - pub fn borrow(&self) -> &T { - self.get() - } -} - #[derive(Debug)] pub struct Lock(InnerLock); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index d3c7b7a068bc3..61389028cc78c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -128,6 +128,7 @@ const WHITELIST: &[&str] = &[ "miniz_oxide", "nodrop", "num_cpus", + "once_cell", "opaque-debug", "parking_lot", "parking_lot_core", From c282c1c654901bd523774dd7ce2e8d4272d24911 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 15 May 2020 21:44:28 -0700 Subject: [PATCH 2/4] Use `OnceCell` instead of `Once` --- Cargo.lock | 3 + src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_codegen_llvm/context.rs | 2 +- src/librustc_codegen_ssa/back/link.rs | 9 +-- src/librustc_codegen_ssa/back/linker.rs | 3 +- .../back/symbol_export.rs | 4 +- src/librustc_codegen_ssa/back/write.rs | 6 +- src/librustc_codegen_ssa/base.rs | 2 +- src/librustc_driver/lib.rs | 2 +- src/librustc_driver/pretty.rs | 4 +- src/librustc_interface/passes.rs | 21 ++++--- src/librustc_interface/queries.rs | 6 +- src/librustc_interface/util.rs | 2 +- src/librustc_metadata/creader.rs | 4 +- src/librustc_metadata/dependency_format.rs | 3 +- src/librustc_metadata/locator.rs | 2 +- src/librustc_metadata/rmeta/decoder.rs | 8 +-- src/librustc_metadata/rmeta/encoder.rs | 4 +- src/librustc_middle/middle/limits.rs | 8 +-- src/librustc_middle/ty/context.rs | 2 +- src/librustc_middle/ty/layout.rs | 2 +- src/librustc_middle/ty/query/on_disk_cache.rs | 14 ++--- src/librustc_mir/const_eval/eval_queries.rs | 4 +- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 5 +- src/librustc_passes/entry.rs | 2 +- src/librustc_passes/reachable.rs | 2 +- src/librustc_passes/weak_lang_items.rs | 2 +- src/librustc_save_analysis/lib.rs | 5 +- src/librustc_session/parse.rs | 6 +- src/librustc_session/session.rs | 55 +++++++++++++------ .../traits/error_reporting/suggestions.rs | 2 +- .../traits/project.rs | 6 +- .../traits/query/normalize.rs | 2 +- src/librustc_trait_selection/traits/select.rs | 3 +- src/librustc_traits/dropck_outlives.rs | 2 +- src/librustc_ty/needs_drop.rs | 3 +- src/librustc_typeck/check/autoderef.rs | 4 +- .../clippy/clippy_lints/src/missing_inline.rs | 2 +- 39 files changed, 118 insertions(+), 102 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebcc11d2b26d6..2fdbfa26787e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2327,6 +2327,9 @@ name = "once_cell" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0" +dependencies = [ + "parking_lot 0.9.0", +] [[package]] name = "opaque-debug" diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 2cf81af04166c..0eabb726b88c9 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -269,7 +269,7 @@ pub fn lower_crate<'a, 'hir>( let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); LoweringContext { - crate_root: sess.parse_sess.injected_crate_name.try_get().copied(), + crate_root: sess.parse_sess.injected_crate_name.get().copied(), sess, resolver, nt_to_tokenstream, diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 3192d4fc15701..4c810a37d4180 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -174,7 +174,7 @@ pub unsafe fn create_module( llvm::LLVMRustSetModulePICLevel(llmod); // PIE is potentially more effective than PIC, but can only be used in executables. // If all our outputs are executables, then we can relax PIC to PIE. - if sess.crate_types.get().iter().all(|ty| *ty == CrateType::Executable) { + if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) { llvm::LLVMRustSetModulePIELevel(llmod); } } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 5de60b5b9c826..9a7c4907754b0 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -53,7 +53,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( ) { let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); - for &crate_type in sess.crate_types.borrow().iter() { + for &crate_type in sess.crate_types().iter() { // Ignore executable crates if we have -Z no-codegen, as they will error. if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) && !output_metadata @@ -875,11 +875,8 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { // If we're only producing artifacts that are archives, no need to preserve // the objects as they're losslessly contained inside the archives. - let output_linked = sess - .crate_types - .borrow() - .iter() - .any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib); + let output_linked = + sess.crate_types().iter().any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib); if !output_linked { return false; } diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index ee5bcf4b9f58b..49de8c5e28ab5 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -44,8 +44,7 @@ impl LinkerInfo { LinkerInfo { exports: tcx .sess - .crate_types - .borrow() + .crate_types() .iter() .map(|&c| (c, exported_symbols(tcx, c))) .collect(), diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index c0272e1cd2d6b..970d13b30c04e 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{SymbolName, TyCtxt}; use rustc_session::config::{CrateType, Sanitizer}; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { - crates_export_threshold(&tcx.sess.crate_types.borrow()) + crates_export_threshold(&tcx.sess.crate_types()) } fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel { @@ -212,7 +212,7 @@ fn exported_symbols_provider_local( })); } - if tcx.sess.crate_types.borrow().contains(&CrateType::Dylib) { + if tcx.sess.crate_types().contains(&CrateType::Dylib) { let symbol_name = metadata_symbol_name(tcx); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index f9ee7d8c5de71..9e03c283cfb5c 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -382,7 +382,7 @@ pub struct CompiledModules { fn need_bitcode_in_object(sess: &Session) -> bool { let requested_for_rlib = sess.opts.cg.embed_bitcode - && sess.crate_types.borrow().contains(&CrateType::Rlib) + && sess.crate_types().contains(&CrateType::Rlib) && sess.opts.output_types.contains_key(&OutputType::Exe); let forced_by_target = sess.target.target.options.forces_embed_bitcode; requested_for_rlib || forced_by_target @@ -991,7 +991,7 @@ fn start_executing_work( }; let cgcx = CodegenContext:: { backend: backend.clone(), - crate_types: sess.crate_types.borrow().clone(), + crate_types: sess.crate_types().to_vec(), each_linked_rlib_for_lto, lto: sess.lto(), no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort, @@ -1812,7 +1812,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool { ); tcx.sess.target.target.options.is_like_msvc && - tcx.sess.crate_types.borrow().iter().any(|ct| *ct == CrateType::Rlib) && + tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) && // ThinLTO can't handle this workaround in all cases, so we don't // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing // dynamic linking when linker plugin LTO is enabled. diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index ed5448ca8bac4..5b14258bd25be 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -948,7 +948,7 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR match compute_per_cgu_lto_type( &tcx.sess.lto(), &tcx.sess.opts, - &tcx.sess.crate_types.borrow(), + &tcx.sess.crate_types(), ModuleKind::Regular, ) { ComputedLtoType::No => CguReuse::PostLto, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6847b175e60eb..68ce93d3db90f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -586,7 +586,7 @@ impl RustcDefaultCalls { if let Input::File(file) = compiler.input() { // FIXME: #![crate_type] and #![crate_name] support not implemented yet let attrs = vec![]; - sess.crate_types.set(collect_crate_types(sess, &attrs)); + sess.init_crate_types(collect_crate_types(sess, &attrs)); let outputs = compiler.build_output_filenames(&sess, &attrs); let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| { sess.fatal(&format!("failed to read rlink file: {}", err)); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index a443b8f464f1c..0a21eb8de059c 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -396,7 +396,7 @@ pub fn print_after_parsing( annotation.pp_ann(), false, parse.edition, - parse.injected_crate_name.try_get().is_some(), + parse.injected_crate_name.get().is_some(), ) }) } else { @@ -438,7 +438,7 @@ pub fn print_after_hir_lowering<'tcx>( annotation.pp_ann(), true, parse.edition, - parse.injected_crate_name.try_get().is_some(), + parse.injected_crate_name.get().is_some(), ) }) } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 801c8e9329b24..214701db724ec 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -7,7 +7,7 @@ use rustc_ast::mut_visit::MutVisitor; use rustc_ast::{self, ast, visit}; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::sync::{par_iter, Lrc, Once, ParallelIterator, WorkerLocal}; +use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal}; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; @@ -169,10 +169,10 @@ pub fn register_plugins<'a>( sess.init_features(features); let crate_types = util::collect_crate_types(sess, &krate.attrs); - sess.crate_types.set(crate_types); + sess.init_crate_types(crate_types); let disambiguator = util::compute_crate_disambiguator(sess); - sess.crate_disambiguator.set(disambiguator); + sess.crate_disambiguator.set(disambiguator).expect("not yet initialized"); rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator); if sess.opts.incremental.is_some() { @@ -244,7 +244,7 @@ fn configure_and_expand_inner<'a>( alt_std_name, ); if let Some(name) = name { - sess.parse_sess.injected_crate_name.set(name); + sess.parse_sess.injected_crate_name.set(name).expect("not yet initialized"); } krate }); @@ -288,7 +288,7 @@ fn configure_and_expand_inner<'a>( let features = sess.features_untracked(); let cfg = rustc_expand::expand::ExpansionConfig { features: Some(&features), - recursion_limit: *sess.recursion_limit.get(), + recursion_limit: sess.recursion_limit(), trace_mac: sess.opts.debugging_opts.trace_macros, should_test: sess.opts.test, ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) @@ -358,7 +358,7 @@ fn configure_and_expand_inner<'a>( rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer()) }); - let crate_types = sess.crate_types.borrow(); + let crate_types = sess.crate_types(); let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); // For backwards compatibility, we don't try to run proc macro injection @@ -488,7 +488,7 @@ fn generated_output_paths( // If the filename has been overridden using `-o`, it will not be modified // by appending `.rlib`, `.exe`, etc., so we can skip this transformation. OutputType::Exe if !exact_name => { - for crate_type in sess.crate_types.borrow().iter() { + for crate_type in sess.crate_types().iter() { let p = filename_for_input(sess, *crate_type, crate_name, outputs); out_filenames.push(p); } @@ -721,7 +721,7 @@ pub fn create_global_ctxt<'tcx>( mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, - global_ctxt: &'tcx Once>, + global_ctxt: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { let sess = &compiler.session(); @@ -743,7 +743,7 @@ pub fn create_global_ctxt<'tcx>( } let gcx = sess.time("setup_global_ctxt", || { - global_ctxt.init_locking(|| { + global_ctxt.get_or_init(|| { TyCtxt::create_global_ctxt( sess, lint_store, @@ -905,8 +905,7 @@ fn encode_and_write_metadata( let metadata_kind = tcx .sess - .crate_types - .borrow() + .crate_types() .iter() .map(|ty| match *ty { CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => MetadataKind::None, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 94cd4bcd4c626..283be165c192c 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -3,7 +3,7 @@ use crate::passes::{self, BoxedResolver, QueryContext}; use rustc_ast::{self, ast}; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_data_structures::sync::{Lrc, Once, WorkerLocal}; +use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::ErrorReported; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::Crate; @@ -65,7 +65,7 @@ impl Default for Query { pub struct Queries<'tcx> { compiler: &'tcx Compiler, - gcx: Once>, + gcx: OnceCell>, arena: WorkerLocal>, hir_arena: WorkerLocal>, @@ -86,7 +86,7 @@ impl<'tcx> Queries<'tcx> { pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> { Queries { compiler, - gcx: Once::new(), + gcx: OnceCell::new(), arena: WorkerLocal::new(|_| Arena::default()), hir_arena: WorkerLocal::new(|_| rustc_ast_lowering::Arena::default()), dep_graph_future: Default::default(), diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 5a76802014e0d..a15da94a21561 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -406,7 +406,7 @@ pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguat // Also incorporate crate type, so that we don't get symbol conflicts when // linking against a library of the same name, if this is an executable. - let is_exe = session.crate_types.borrow().contains(&CrateType::Executable); + let is_exe = session.crate_types().contains(&CrateType::Executable); hasher.write(if is_exe { b"exe" } else { b"lib" }); CrateDisambiguator::from(hasher.finish::()) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index a9e7a9f35dc36..b0220ddd3c38e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -615,7 +615,7 @@ impl<'a> CrateLoader<'a> { fn inject_panic_runtime(&mut self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. - let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| *ct != CrateType::Rlib); + let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib); if !any_non_rlib { info!("panic runtime injection skipped, only generating rlib"); return; @@ -734,7 +734,7 @@ impl<'a> CrateLoader<'a> { // At this point we've determined that we need an allocator. Let's see // if our compilation session actually needs an allocator based on what // we're emitting. - let all_rlib = self.sess.crate_types.borrow().iter().all(|ct| match *ct { + let all_rlib = self.sess.crate_types().iter().all(|ct| match *ct { CrateType::Rlib => true, _ => false, }); diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 0876cd1e63835..aa5fafcc614b6 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -64,8 +64,7 @@ use rustc_target::spec::PanicStrategy; crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies { tcx.sess - .crate_types - .borrow() + .crate_types() .iter() .map(|&ty| { let linkage = calculate_type(tcx, ty); diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index f78f3c5d8d40f..5a4862d452183 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -670,7 +670,7 @@ impl<'a> CrateLocator<'a> { // The all loop is because `--crate-type=rlib --crate-type=rlib` is // legal and produces both inside this type. - let is_rlib = self.sess.crate_types.borrow().iter().all(|c| *c == CrateType::Rlib); + let is_rlib = self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib); let needs_object_code = self.sess.opts.output_types.should_codegen(); // If we're producing an rlib, then we don't need object code. // Or, if we're not producing object code, then we don't need it either diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 220d74960755f..2b292b35c159d 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -10,7 +10,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once}; +use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive}; use rustc_hir as hir; @@ -79,7 +79,7 @@ crate struct CrateMetadata { /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. - source_map_import_info: Once>, + source_map_import_info: OnceCell>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. alloc_decoding_state: AllocDecodingState, /// The `DepNodeIndex` of the `DepNode` representing this upstream crate. @@ -1486,7 +1486,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } }; - self.cdata.source_map_import_info.init_locking(|| { + self.cdata.source_map_import_info.get_or_init(|| { let external_source_map = self.root.source_map.decode(self); external_source_map @@ -1600,7 +1600,7 @@ impl CrateMetadata { def_path_table, trait_impls, raw_proc_macros, - source_map_import_info: Once::new(), + source_map_import_info: OnceCell::new(), alloc_decoding_state, dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), cnum, diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index ebe91d3cee2aa..91fbfcc0133eb 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -416,7 +416,7 @@ impl<'tcx> EncodeContext<'tcx> { } fn encode_crate_root(&mut self) -> Lazy> { - let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); + let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro); let mut i = self.position(); @@ -1364,7 +1364,7 @@ impl EncodeContext<'tcx> { } fn encode_proc_macros(&mut self) -> Option> { - let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); + let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro); if is_proc_macro { let tcx = self.tcx; Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))) diff --git a/src/librustc_middle/middle/limits.rs b/src/librustc_middle/middle/limits.rs index c43c22cd61ba6..19c056925cf92 100644 --- a/src/librustc_middle/middle/limits.rs +++ b/src/librustc_middle/middle/limits.rs @@ -7,7 +7,7 @@ use crate::bug; use rustc_ast::ast; -use rustc_data_structures::sync::Once; +use rustc_data_structures::sync::OnceCell; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; @@ -22,7 +22,7 @@ pub fn update_limits(sess: &Session, krate: &ast::Crate) { fn update_limit( sess: &Session, krate: &ast::Crate, - limit: &Once, + limit: &OnceCell, name: Symbol, default: usize, ) { @@ -34,7 +34,7 @@ fn update_limit( if let Some(s) = attr.value_str() { match s.as_str().parse() { Ok(n) => { - limit.set(n); + limit.set(n).unwrap(); return; } Err(e) => { @@ -62,5 +62,5 @@ fn update_limit( } } } - limit.set(default); + limit.set(default).unwrap(); } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 5d48b3445e8a1..68c31c68075e0 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1380,7 +1380,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn local_crate_exports_generics(self) -> bool { debug_assert!(self.sess.opts.share_generics()); - self.sess.crate_types.borrow().iter().any(|crate_type| { + self.sess.crate_types().iter().any(|crate_type| { match crate_type { CrateType::Executable | CrateType::Staticlib diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index 2d49d85c4df54..5566e187c0c5c 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -187,7 +187,7 @@ fn layout_raw<'tcx>( query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Result<&'tcx Layout, LayoutError<'tcx>> { ty::tls::with_related_context(tcx, move |icx| { - let rec_limit = *tcx.sess.recursion_limit.get(); + let rec_limit = tcx.sess.recursion_limit.get().copied().unwrap(); let (param_env, ty) = query.into_parts(); if icx.layout_depth > rec_limit { diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs index 71c2c24cc0a9f..4eae06742d9d3 100644 --- a/src/librustc_middle/ty/query/on_disk_cache.rs +++ b/src/librustc_middle/ty/query/on_disk_cache.rs @@ -6,7 +6,7 @@ use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once}; +use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::Diagnostic; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; @@ -49,7 +49,7 @@ pub struct OnDiskCache<'sess> { current_diagnostics: Lock>>, prev_cnums: Vec<(u32, String, CrateDisambiguator)>, - cnum_map: Once>>, + cnum_map: OnceCell>>, source_map: &'sess SourceMap, file_index_to_stable_id: FxHashMap, @@ -128,7 +128,7 @@ impl<'sess> OnDiskCache<'sess> { file_index_to_stable_id: footer.file_index_to_stable_id, file_index_to_file: Default::default(), prev_cnums: footer.prev_cnums, - cnum_map: Once::new(), + cnum_map: OnceCell::new(), source_map: sess.source_map(), current_diagnostics: Default::default(), query_result_index: footer.query_result_index.into_iter().collect(), @@ -144,7 +144,7 @@ impl<'sess> OnDiskCache<'sess> { file_index_to_stable_id: Default::default(), file_index_to_file: Default::default(), prev_cnums: vec![], - cnum_map: Once::new(), + cnum_map: OnceCell::new(), source_map, current_diagnostics: Default::default(), query_result_index: Default::default(), @@ -370,14 +370,14 @@ impl<'sess> OnDiskCache<'sess> { { let pos = index.get(&dep_node_index).cloned()?; - // Initialize `cnum_map` using the value from the thread that finishes the closure first. - self.cnum_map.init_nonlocking_same(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..])); + let cnum_map = + self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..])); let mut decoder = CacheDecoder { tcx, opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()), source_map: self.source_map, - cnum_map: self.cnum_map.get(), + cnum_map, synthetic_syntax_contexts: &self.synthetic_syntax_contexts, file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 0637ebf959e5a..fd5e0632a2c10 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -89,7 +89,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( InterpCx::new( tcx.at(span), param_env, - CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()), + CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), MemoryExtra { can_access_statics }, ) } @@ -303,7 +303,7 @@ pub fn const_eval_raw_provider<'tcx>( let mut ecx = InterpCx::new( tcx.at(span), key.param_env, - CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()), + CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), MemoryExtra { can_access_statics: is_static }, ); diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index eba4dd336ade2..4f91257e2ef83 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -651,7 +651,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::after_stack_push(self)?; info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance); - if self.stack().len() > *self.tcx.sess.recursion_limit.get() { + if self.stack().len() > self.tcx.sess.recursion_limit() { throw_exhaust!(StackFrameLimitReached) } else { Ok(()) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 925b8d329668f..081f6435d9db9 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -430,7 +430,7 @@ fn check_recursion_limit<'tcx>( // Code that needs to instantiate the same function recursively // more than the recursion limit is assumed to be causing an // infinite expansion. - if adjusted_recursion_depth > *tcx.sess.recursion_limit.get() { + if adjusted_recursion_depth > tcx.sess.recursion_limit() { let error = format!("reached the recursion limit while instantiating `{}`", instance); if let Some(def_id) = def_id.as_local() { let hir_id = tcx.hir().as_local_hir_id(def_id); @@ -463,8 +463,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { // which means that rustc basically hangs. // // Bail out in these cases to avoid that bad user experience. - let type_length_limit = *tcx.sess.type_length_limit.get(); - if type_length > type_length_limit { + if type_length > tcx.sess.type_length_limit() { // The instance name is already known to be too long for rustc. // Show only the first and last 32 characters to avoid blasting // the user's terminal with thousands of lines of type-name. diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index d2f1d11256bf2..e0ad0ac77476f 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -51,7 +51,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(LocalDefId, EntryFnType)> { assert_eq!(cnum, LOCAL_CRATE); - let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| *ty == CrateType::Executable); + let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable); if !any_exe { // No need to find a main function. return None; diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 7c169d6813282..cac71b3836c54 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -376,7 +376,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); let any_library = - tcx.sess.crate_types.borrow().iter().any(|ty| { + tcx.sess.crate_types().iter().any(|ty| { *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro }); let mut reachable_context = ReachableContext { diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index 8a581626862a2..96ec23692df51 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -37,7 +37,7 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { // We only need to check for the presence of weak lang items if we're // emitting something that's not an rlib. - let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| match *kind { + let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind { CrateType::Dylib | CrateType::ProcMacro | CrateType::Cdylib diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 43fd2b1853011..3bd68a9c656ce 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -87,7 +87,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { pub fn compilation_output(&self, crate_name: &str) -> PathBuf { let sess = &self.tcx.sess; // Save-analysis is emitted per whole session, not per each crate type - let crate_type = sess.crate_types.borrow()[0]; + let crate_type = sess.crate_types()[0]; let outputs = &*self.tcx.output_filenames(LOCAL_CRATE); if outputs.outputs.contains_key(&OutputType::Metadata) { @@ -987,8 +987,7 @@ impl<'a> DumpHandler<'a> { error!("Could not create directory {}: {}", root_path.display(), e); } - let executable = - sess.crate_types.borrow().iter().any(|ct| *ct == CrateType::Executable); + let executable = sess.crate_types().iter().any(|ct| *ct == CrateType::Executable); let mut out_name = if executable { String::new() } else { "lib".to_owned() }; out_name.push_str(&self.cratename); out_name.push_str(&sess.opts.cg.extra_filename); diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 69d3e99b7458e..746e3536ce908 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -4,7 +4,7 @@ use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId}; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::{Lock, Lrc, Once}; +use rustc_data_structures::sync::{Lock, Lrc, OnceCell}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{error_code, Applicability, DiagnosticBuilder}; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; @@ -130,7 +130,7 @@ pub struct ParseSess { /// operation token that followed it, but that the parser cannot identify without further /// analysis. pub ambiguous_block_expr_parse: Lock>, - pub injected_crate_name: Once, + pub injected_crate_name: OnceCell, pub gated_spans: GatedSpans, pub symbol_gallery: SymbolGallery, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. @@ -156,7 +156,7 @@ impl ParseSess { source_map, buffered_lints: Lock::new(vec![]), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - injected_crate_name: Once::new(), + injected_crate_name: OnceCell::new(), gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), reached_eof: Lock::new(false), diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 143401dd3b622..f2f02cb649463 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -13,7 +13,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{duration_to_secs_str, SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ - self, AtomicU64, AtomicUsize, Lock, Lrc, Once, OneThread, Ordering, Ordering::SeqCst, + self, AtomicU64, AtomicUsize, Lock, Lrc, OnceCell, OneThread, Ordering, Ordering::SeqCst, }; use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitterWriter; use rustc_errors::emitter::{Emitter, EmitterWriter, HumanReadableErrorType}; @@ -77,25 +77,25 @@ pub struct Session { /// (sub)diagnostics that have been set once, but should not be set again, /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: Lock, String)>>, - pub crate_types: Once>, + crate_types: OnceCell>, /// The `crate_disambiguator` is constructed out of all the `-C metadata` /// arguments passed to the compiler. Its value together with the crate-name /// forms a unique global identifier for the crate. It is used to allow /// multiple crates with the same name to coexist. See the /// `rustc_codegen_llvm::back::symbol_names` module for more information. - pub crate_disambiguator: Once, + pub crate_disambiguator: OnceCell, - features: Once, + features: OnceCell, /// The maximum recursion limit for potentially infinitely recursive /// operations such as auto-dereference and monomorphization. - pub recursion_limit: Once, + pub recursion_limit: OnceCell, /// The maximum length of types during monomorphization. - pub type_length_limit: Once, + pub type_length_limit: OnceCell, /// The maximum blocks a const expression can evaluate. - pub const_eval_limit: Once, + pub const_eval_limit: OnceCell, incr_comp_session: OneThread>, /// Used for incremental compilation tests. Will only be populated if @@ -244,7 +244,27 @@ impl Session { } pub fn local_crate_disambiguator(&self) -> CrateDisambiguator { - *self.crate_disambiguator.get() + self.crate_disambiguator.get().copied().unwrap() + } + + pub fn crate_types(&self) -> &[CrateType] { + self.crate_types.get().unwrap().as_slice() + } + + pub fn init_crate_types(&self, crate_types: Vec) { + self.crate_types.set(crate_types).expect("`crate_types` was initialized twice") + } + + pub fn recursion_limit(&self) -> usize { + self.recursion_limit.get().copied().unwrap() + } + + pub fn type_length_limit(&self) -> usize { + self.type_length_limit.get().copied().unwrap() + } + + pub fn const_eval_limit(&self) -> usize { + self.const_eval_limit.get().copied().unwrap() } pub fn struct_span_warn>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'_> { @@ -500,11 +520,14 @@ impl Session { /// dependency tracking. Use tcx.features() instead. #[inline] pub fn features_untracked(&self) -> &rustc_feature::Features { - self.features.get() + self.features.get().unwrap() } pub fn init_features(&self, features: rustc_feature::Features) { - self.features.set(features); + match self.features.set(features) { + Ok(()) => {} + Err(_) => panic!("`features` was initialized twice"), + } } /// Calculates the flavor of LTO to use for this compilation. @@ -1208,12 +1231,12 @@ pub fn build_session_with_source_map( local_crate_source_file, working_dir, one_time_diagnostics: Default::default(), - crate_types: Once::new(), - crate_disambiguator: Once::new(), - features: Once::new(), - recursion_limit: Once::new(), - type_length_limit: Once::new(), - const_eval_limit: Once::new(), + crate_types: OnceCell::new(), + crate_disambiguator: OnceCell::new(), + features: OnceCell::new(), + recursion_limit: OnceCell::new(), + type_length_limit: OnceCell::new(), + const_eval_limit: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, prof, diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 0760bd523b7c3..50a59469d8530 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1875,7 +1875,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { - let current_limit = self.tcx.sess.recursion_limit.get(); + let current_limit = self.tcx.sess.recursion_limit(); let suggested_limit = current_limit * 2; err.help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 9b63cbdd83cac..914485fd408fc 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -332,7 +332,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { Reveal::UserFacing => ty, Reveal::All => { - let recursion_limit = *self.tcx().sess.recursion_limit.get(); + let recursion_limit = self.tcx().sess.recursion_limit(); if self.depth >= recursion_limit { let obligation = Obligation::with_depth( self.cause.clone(), @@ -520,7 +520,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( ); // But for now, let's classify this as an overflow: - let recursion_limit = *selcx.tcx().sess.recursion_limit.get(); + let recursion_limit = selcx.tcx().sess.recursion_limit(); let obligation = Obligation::with_depth(cause, recursion_limit, param_env, projection_ty); selcx.infcx().report_overflow_error(&obligation, false); @@ -814,7 +814,7 @@ fn project_type<'cx, 'tcx>( ) -> Result, ProjectionTyError<'tcx>> { debug!("project(obligation={:?})", obligation); - let recursion_limit = *selcx.tcx().sess.recursion_limit.get(); + let recursion_limit = selcx.tcx().sess.recursion_limit(); if obligation.recursion_depth >= recursion_limit { debug!("project: overflow!"); return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow)); diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs index 3b985a4b150fa..008ca8d526dd3 100644 --- a/src/librustc_trait_selection/traits/query/normalize.rs +++ b/src/librustc_trait_selection/traits/query/normalize.rs @@ -108,7 +108,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { Reveal::UserFacing => ty, Reveal::All => { - let recursion_limit = *self.tcx().sess.recursion_limit.get(); + let recursion_limit = self.tcx().sess.recursion_limit(); if self.anon_depth >= recursion_limit { let obligation = Obligation::with_depth( self.cause.clone(), diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index 6110d6470df90..b402aba65cdb7 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -919,8 +919,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &Obligation<'tcx, T>, error_obligation: &Obligation<'tcx, V>, ) -> Result<(), OverflowError> { - let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get(); - if obligation.recursion_depth >= recursion_limit { + if obligation.recursion_depth >= self.infcx.tcx.sess.recursion_limit() { match self.query_mode { TraitQueryMode::Standard => { self.infcx().report_overflow_error(error_obligation, true); diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 08475d6a09db1..fb9c0d7f99013 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>( ) -> Result<(), NoSolution> { debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty); - if depth >= *tcx.sess.recursion_limit.get() { + if depth >= tcx.sess.recursion_limit() { constraints.overflows.push(ty); return Ok(()); } diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs index 97994b465b54c..e94a47f079a63 100644 --- a/src/librustc_ty/needs_drop.rs +++ b/src/librustc_ty/needs_drop.rs @@ -43,14 +43,13 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { ) -> Self { let mut seen_tys = FxHashSet::default(); seen_tys.insert(ty); - let recursion_limit = *tcx.sess.recursion_limit.get(); Self { tcx, param_env, seen_tys, query_ty: ty, unchecked_tys: vec![(ty, 0)], - recursion_limit, + recursion_limit: tcx.sess.recursion_limit(), adt_components, } } diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 8ca0861090605..d4c01a82e0aa5 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -48,7 +48,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { return Some((self.cur_ty, 0)); } - if self.steps.len() >= *tcx.sess.recursion_limit.get() { + if self.steps.len() >= tcx.sess.recursion_limit() { if !self.silence_errors { report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty); } @@ -236,7 +236,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { // We've reached the recursion limit, error gracefully. - let suggested_limit = *tcx.sess.recursion_limit.get() * 2; + let suggested_limit = tcx.sess.recursion_limit() * 2; let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`", ty); let error_id = (DiagnosticMessageId::ErrorId(55), Some(span), msg); let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 5300fd2215b39..3ad3d5aee4d4a 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -71,7 +71,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute] fn is_executable(cx: &LateContext<'_, '_>) -> bool { use rustc_session::config::CrateType; - cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t { + cx.tcx.sess.crate_types().iter().any(|t: &CrateType| match t { CrateType::Executable => true, _ => false, }) From f17e2c93a69443c93aa42e0df0a119d35c4d49d9 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 15 May 2020 21:56:33 -0700 Subject: [PATCH 3/4] Use `OnceCell` for predecessor cache --- src/librustc_middle/mir/predecessors.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/librustc_middle/mir/predecessors.rs b/src/librustc_middle/mir/predecessors.rs index 9508365886aa7..36e92c71c07f4 100644 --- a/src/librustc_middle/mir/predecessors.rs +++ b/src/librustc_middle/mir/predecessors.rs @@ -1,7 +1,7 @@ //! Lazily compute the reverse control-flow graph for the MIR. use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::sync::OnceCell; use rustc_index::vec::IndexVec; use rustc_serialize as serialize; use smallvec::SmallVec; @@ -13,13 +13,13 @@ pub type Predecessors = IndexVec>; #[derive(Clone, Debug)] pub(super) struct PredecessorCache { - cache: Lock>>, + cache: OnceCell, } impl PredecessorCache { #[inline] pub(super) fn new() -> Self { - PredecessorCache { cache: Lock::new(None) } + PredecessorCache { cache: OnceCell::new() } } /// Invalidates the predecessor cache. @@ -27,23 +27,19 @@ impl PredecessorCache { /// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a /// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all /// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor - /// cache. This means we don't actually need to take a lock when `invalidate` is called. + /// cache. This means we never need to do synchronization when `invalidate` is called. #[inline] pub(super) fn invalidate(&mut self) { - *self.cache.get_mut() = None; + self.cache = OnceCell::new(); } - /// Returns a ref-counted smart pointer containing the predecessor graph for this MIR. - /// - /// We use ref-counting instead of a mapped `LockGuard` here to ensure that the lock for - /// `cache` is only held inside this function. As long as no other locks are taken while - /// computing the predecessor graph, deadlock is impossible. + /// Returns the the predecessor graph for this MIR. #[inline] pub(super) fn compute( &self, basic_blocks: &IndexVec>, - ) -> Lrc { - Lrc::clone(self.cache.lock().get_or_insert_with(|| { + ) -> &Predecessors { + self.cache.get_or_init(|| { let mut preds = IndexVec::from_elem(SmallVec::new(), basic_blocks); for (bb, data) in basic_blocks.iter_enumerated() { if let Some(term) = &data.terminator { @@ -53,8 +49,8 @@ impl PredecessorCache { } } - Lrc::new(preds) - })) + preds + }) } } From 307153e611433f9224224a4511b6ea4f362ffe28 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 16 May 2020 11:26:21 -0700 Subject: [PATCH 4/4] Switch to non-doc comment --- src/librustc_middle/mir/predecessors.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_middle/mir/predecessors.rs b/src/librustc_middle/mir/predecessors.rs index 36e92c71c07f4..7508c0239397f 100644 --- a/src/librustc_middle/mir/predecessors.rs +++ b/src/librustc_middle/mir/predecessors.rs @@ -23,13 +23,13 @@ impl PredecessorCache { } /// Invalidates the predecessor cache. - /// - /// Invalidating the predecessor cache requires mutating the MIR, which in turn requires a - /// unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all - /// callers of `invalidate` have a unique reference to the MIR and thus to the predecessor - /// cache. This means we never need to do synchronization when `invalidate` is called. #[inline] pub(super) fn invalidate(&mut self) { + // Invalidating the predecessor cache requires mutating the MIR, which in turn requires a + // unique reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all + // callers of `invalidate` have a unique reference to the MIR and thus to the predecessor + // cache. This means we never need to do synchronization when `invalidate` is called, we can + // simply reinitialize the `OnceCell`. self.cache = OnceCell::new(); }