Auto merge of #72256 - ecstatic-morse:once-cell, r=Mark-Simulacrum
Use `once_cell` crate instead of custom data structure Internally, we use the [`Once`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/sync/struct.Once.html) type for shared data that is initialized exactly once and only read from afterwards. `Once` uses a `parking_lot::Mutex` when the parallel compiler is enabled and a `RefCell` when it is not. This PR switches to the [`once_cell`](https://crates.io/crates/once_cell) crate, which also uses a `parking_lot::Mutex` for its `sync` version (because we enable the `parking_lot` feature) but has zero overhead for its `unsync` one. This PR adds `once_cell` to the list of whitelisted dependencies. I think this is acceptable because it is already used in `rustc_driver`, is owned by a well-known community member (cc @matklad), and has a stable release. cc @rust-lang/compiler `once_cell` has a slightly more minimal API than `Once`, which allows for initialization to be either optimistic (evaluate the initializer and then synchronize) or pessimistic (synchronize and then evaluate the initializer). `once_cell`'s `get_or_init` is always pessimistic. The optimistic version is only used once in the current `master`. r? @Mark-Simulacrum
This commit is contained in:
commit
7f940ef5d9
43 changed files with 139 additions and 249 deletions
|
|
@ -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"
|
||||
|
|
@ -3791,6 +3794,7 @@ dependencies = [
|
|||
"libc",
|
||||
"log",
|
||||
"measureme",
|
||||
"once_cell",
|
||||
"parking_lot 0.10.2",
|
||||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,7 @@ impl LinkerInfo {
|
|||
LinkerInfo {
|
||||
exports: tcx
|
||||
.sess
|
||||
.crate_types
|
||||
.borrow()
|
||||
.crate_types()
|
||||
.iter()
|
||||
.map(|&c| (c, exported_symbols(tcx, c)))
|
||||
.collect(),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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<B: ExtraBackendMethods>(
|
|||
};
|
||||
let cgcx = CodegenContext::<B> {
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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<K: Eq + Hash, V: Eq, S: BuildHasher> HashMapExt<K, V> for HashMap<K, V, S>
|
|||
}
|
||||
}
|
||||
|
||||
/// A type whose inner value can be written once and then will stay read-only
|
||||
// This contains a PhantomData<T> since this type conceptually owns a T outside the Mutex once
|
||||
// initialized. This ensures that Once<T> is Sync only if T is. If we did not have PhantomData<T>
|
||||
// we could send a &Once<Cell<bool>> to multiple threads and call `get` on it to get access
|
||||
// to &Cell<bool> on those threads.
|
||||
pub struct Once<T>(Lock<Option<T>>, PhantomData<T>);
|
||||
|
||||
impl<T> Once<T> {
|
||||
/// 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<T> {
|
||||
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<T> {
|
||||
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<T>
|
||||
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<F: FnOnce() -> 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<F: FnOnce() -> T>(&self, f: F) -> Option<T> {
|
||||
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<F: FnOnce() -> T>(&self, f: F) -> Option<T>
|
||||
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<T>(InnerLock<T>);
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<GlobalCtxt<'tcx>>,
|
||||
global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
|
||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
) -> 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,
|
||||
|
|
|
|||
|
|
@ -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<T> Default for Query<T> {
|
|||
|
||||
pub struct Queries<'tcx> {
|
||||
compiler: &'tcx Compiler,
|
||||
gcx: Once<GlobalCtxt<'tcx>>,
|
||||
gcx: OnceCell<GlobalCtxt<'tcx>>,
|
||||
|
||||
arena: WorkerLocal<Arena<'tcx>>,
|
||||
hir_arena: WorkerLocal<rustc_ast_lowering::Arena<'tcx>>,
|
||||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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::<Fingerprint>())
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Vec<ImportedSourceFile>>,
|
||||
source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
|
||||
/// 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,
|
||||
|
|
|
|||
|
|
@ -416,7 +416,7 @@ impl<'tcx> EncodeContext<'tcx> {
|
|||
}
|
||||
|
||||
fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
|
||||
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<Lazy<[DefIndex]>> {
|
||||
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)))
|
||||
|
|
|
|||
|
|
@ -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<usize>,
|
||||
limit: &OnceCell<usize>,
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,37 +13,33 @@ pub type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(super) struct PredecessorCache {
|
||||
cache: Lock<Option<Lrc<Predecessors>>>,
|
||||
cache: OnceCell<Predecessors>,
|
||||
}
|
||||
|
||||
impl PredecessorCache {
|
||||
#[inline]
|
||||
pub(super) fn new() -> Self {
|
||||
PredecessorCache { cache: Lock::new(None) }
|
||||
PredecessorCache { cache: OnceCell::new() }
|
||||
}
|
||||
|
||||
/// 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 don't actually need to take a lock when `invalidate` is called.
|
||||
#[inline]
|
||||
pub(super) fn invalidate(&mut self) {
|
||||
*self.cache.get_mut() = None;
|
||||
// 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();
|
||||
}
|
||||
|
||||
/// 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<BasicBlock, BasicBlockData<'_>>,
|
||||
) -> Lrc<Predecessors> {
|
||||
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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
|
||||
|
||||
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
|
||||
cnum_map: Once<IndexVec<CrateNum, Option<CrateNum>>>,
|
||||
cnum_map: OnceCell<IndexVec<CrateNum, Option<CrateNum>>>,
|
||||
|
||||
source_map: &'sess SourceMap,
|
||||
file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<FxHashMap<Span, Span>>,
|
||||
pub injected_crate_name: Once<Symbol>,
|
||||
pub injected_crate_name: OnceCell<Symbol>,
|
||||
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),
|
||||
|
|
|
|||
|
|
@ -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<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
|
||||
pub crate_types: Once<Vec<CrateType>>,
|
||||
crate_types: OnceCell<Vec<CrateType>>,
|
||||
/// 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<CrateDisambiguator>,
|
||||
pub crate_disambiguator: OnceCell<CrateDisambiguator>,
|
||||
|
||||
features: Once<rustc_feature::Features>,
|
||||
features: OnceCell<rustc_feature::Features>,
|
||||
|
||||
/// The maximum recursion limit for potentially infinitely recursive
|
||||
/// operations such as auto-dereference and monomorphization.
|
||||
pub recursion_limit: Once<usize>,
|
||||
pub recursion_limit: OnceCell<usize>,
|
||||
|
||||
/// The maximum length of types during monomorphization.
|
||||
pub type_length_limit: Once<usize>,
|
||||
pub type_length_limit: OnceCell<usize>,
|
||||
|
||||
/// The maximum blocks a const expression can evaluate.
|
||||
pub const_eval_limit: Once<usize>,
|
||||
pub const_eval_limit: OnceCell<usize>,
|
||||
|
||||
incr_comp_session: OneThread<RefCell<IncrCompSession>>,
|
||||
/// 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<CrateType>) {
|
||||
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<S: Into<MultiSpan>>(&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,
|
||||
|
|
|
|||
|
|
@ -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 (`{}`)",
|
||||
|
|
|
|||
|
|
@ -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<ProjectedTy<'tcx>, 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));
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ const WHITELIST: &[&str] = &[
|
|||
"miniz_oxide",
|
||||
"nodrop",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"opaque-debug",
|
||||
"parking_lot",
|
||||
"parking_lot_core",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue