Skip to content

Commit 6545a2d

Browse files
committed
Immediately enter in TyCtxt::create_global_ctxt
1 parent 954cd79 commit 6545a2d

File tree

2 files changed

+62
-68
lines changed

2 files changed

+62
-68
lines changed

Diff for: compiler/rustc_interface/src/passes.rs

+40-37
Original file line numberDiff line numberDiff line change
@@ -709,25 +709,10 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
709709
*providers
710710
});
711711

712-
pub fn create_and_enter_global_ctxt<T>(
712+
pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
713713
compiler: &Compiler,
714-
krate: rustc_ast::Crate,
715-
f: impl for<'tcx> FnOnce(TyCtxt<'tcx>) -> T,
716-
) -> T {
717-
let gcx_cell = OnceLock::new();
718-
let arena = WorkerLocal::new(|_| Arena::default());
719-
let hir_arena = WorkerLocal::new(|_| rustc_hir::Arena::default());
720-
721-
create_and_enter_global_ctxt_inner(compiler, krate, &gcx_cell, &arena, &hir_arena, f)
722-
}
723-
724-
fn create_and_enter_global_ctxt_inner<'tcx, T>(
725-
compiler: &'tcx Compiler,
726714
mut krate: rustc_ast::Crate,
727-
gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
728-
arena: &'tcx WorkerLocal<Arena<'tcx>>,
729-
hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
730-
f: impl FnOnce(TyCtxt<'tcx>) -> T,
715+
f: F,
731716
) -> T {
732717
let sess = &compiler.sess;
733718

@@ -776,8 +761,25 @@ fn create_and_enter_global_ctxt_inner<'tcx, T>(
776761

777762
let incremental = dep_graph.is_fully_enabled();
778763

779-
let qcx = gcx_cell.get_or_init(move || {
764+
let gcx_cell = OnceLock::new();
765+
let arena = WorkerLocal::new(|_| Arena::default());
766+
let hir_arena = WorkerLocal::new(|_| rustc_hir::Arena::default());
767+
768+
// This closure is necessary to force rustc to perform the correct lifetime
769+
// subtyping for GlobalCtxt::enter to be allowed.
770+
let inner: Box<
771+
dyn for<'tcx> FnOnce(
772+
&'tcx Compiler,
773+
&'tcx OnceLock<GlobalCtxt<'tcx>>,
774+
&'tcx WorkerLocal<Arena<'tcx>>,
775+
&'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
776+
F,
777+
) -> T,
778+
> = Box::new(move |compiler, gcx_cell, arena, hir_arena, f| {
779+
let sess = &compiler.sess;
780+
780781
TyCtxt::create_global_ctxt(
782+
gcx_cell,
781783
sess,
782784
crate_types,
783785
stable_crate_id,
@@ -794,28 +796,29 @@ fn create_and_enter_global_ctxt_inner<'tcx, T>(
794796
),
795797
providers.hooks,
796798
compiler.current_gcx.clone(),
799+
|tcx| {
800+
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
801+
assert_eq!(feed.key(), LOCAL_CRATE);
802+
feed.crate_name(crate_name);
803+
804+
let feed = tcx.feed_unit_query();
805+
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
806+
sess,
807+
&pre_configured_attrs,
808+
crate_name,
809+
)));
810+
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
811+
feed.output_filenames(Arc::new(outputs));
812+
813+
let res = f(tcx);
814+
// FIXME maybe run finish even when a fatal error occured? or at least tcx.alloc_self_profile_query_strings()?
815+
tcx.finish();
816+
res
817+
},
797818
)
798819
});
799820

800-
qcx.enter(|tcx| {
801-
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
802-
assert_eq!(feed.key(), LOCAL_CRATE);
803-
feed.crate_name(crate_name);
804-
805-
let feed = tcx.feed_unit_query();
806-
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
807-
sess,
808-
&pre_configured_attrs,
809-
crate_name,
810-
)));
811-
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
812-
feed.output_filenames(Arc::new(outputs));
813-
814-
let res = f(tcx);
815-
// FIXME maybe run finish even when a fatal error occured? or at least tcx.alloc_self_profile_query_strings()?
816-
tcx.finish();
817-
res
818-
})
821+
inner(compiler, &gcx_cell, &arena, &hir_arena, f)
819822
}
820823

821824
/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.

Diff for: compiler/rustc_middle/src/ty/context.rs

+22-31
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::cmp::Ordering;
1010
use std::hash::{Hash, Hasher};
1111
use std::marker::PhantomData;
1212
use std::ops::{Bound, Deref};
13+
use std::sync::OnceLock;
1314
use std::{fmt, iter, mem};
1415

1516
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
@@ -1347,33 +1348,6 @@ pub struct GlobalCtxt<'tcx> {
13471348

13481349
/// Stores memory for globals (statics/consts).
13491350
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
1350-
1351-
current_gcx: CurrentGcx,
1352-
}
1353-
1354-
impl<'tcx> GlobalCtxt<'tcx> {
1355-
/// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
1356-
/// `f`.
1357-
pub fn enter<F, R>(&'tcx self, f: F) -> R
1358-
where
1359-
F: FnOnce(TyCtxt<'tcx>) -> R,
1360-
{
1361-
let icx = tls::ImplicitCtxt::new(self);
1362-
1363-
// Reset `current_gcx` to `None` when we exit.
1364-
let _on_drop = defer(move || {
1365-
*self.current_gcx.value.write() = None;
1366-
});
1367-
1368-
// Set this `GlobalCtxt` as the current one.
1369-
{
1370-
let mut guard = self.current_gcx.value.write();
1371-
assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
1372-
*guard = Some(self as *const _ as *const ());
1373-
}
1374-
1375-
tls::enter_context(&icx, || f(icx.tcx))
1376-
}
13771351
}
13781352

13791353
/// This is used to get a reference to a `GlobalCtxt` if one is available.
@@ -1517,7 +1491,8 @@ impl<'tcx> TyCtxt<'tcx> {
15171491
/// By only providing the `TyCtxt` inside of the closure we enforce that the type
15181492
/// context and any interned value (types, args, etc.) can only be used while `ty::tls`
15191493
/// has a valid reference to the context, to allow formatting values that need it.
1520-
pub fn create_global_ctxt(
1494+
pub fn create_global_ctxt<T>(
1495+
gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
15211496
s: &'tcx Session,
15221497
crate_types: Vec<CrateType>,
15231498
stable_crate_id: StableCrateId,
@@ -1529,7 +1504,8 @@ impl<'tcx> TyCtxt<'tcx> {
15291504
query_system: QuerySystem<'tcx>,
15301505
hooks: crate::hooks::Providers,
15311506
current_gcx: CurrentGcx,
1532-
) -> GlobalCtxt<'tcx> {
1507+
f: impl FnOnce(TyCtxt<'tcx>) -> T,
1508+
) -> T {
15331509
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
15341510
s.dcx().emit_fatal(err);
15351511
});
@@ -1538,7 +1514,7 @@ impl<'tcx> TyCtxt<'tcx> {
15381514
let common_lifetimes = CommonLifetimes::new(&interners);
15391515
let common_consts = CommonConsts::new(&interners, &common_types, s, &untracked);
15401516

1541-
GlobalCtxt {
1517+
let gcx = gcx_cell.get_or_init(|| GlobalCtxt {
15421518
sess: s,
15431519
crate_types,
15441520
stable_crate_id,
@@ -1562,8 +1538,23 @@ impl<'tcx> TyCtxt<'tcx> {
15621538
canonical_param_env_cache: Default::default(),
15631539
data_layout,
15641540
alloc_map: Lock::new(interpret::AllocMap::new()),
1565-
current_gcx,
1541+
});
1542+
1543+
let icx = tls::ImplicitCtxt::new(&gcx);
1544+
1545+
// Reset `current_gcx` to `None` when we exit.
1546+
let _on_drop = defer(|| {
1547+
*current_gcx.value.write() = None;
1548+
});
1549+
1550+
// Set this `GlobalCtxt` as the current one.
1551+
{
1552+
let mut guard = current_gcx.value.write();
1553+
assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
1554+
*guard = Some(&gcx as *const _ as *const ());
15661555
}
1556+
1557+
tls::enter_context(&icx, || f(icx.tcx))
15671558
}
15681559

15691560
/// Obtain all lang items of this crate and all dependencies (recursively)

0 commit comments

Comments
 (0)