about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_interface/src/passes.rs77
-rw-r--r--compiler/rustc_middle/src/ty/context.rs53
2 files changed, 62 insertions, 68 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 493c55240ea..99cac866306 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -709,25 +709,10 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
     *providers
 });
 
-pub fn create_and_enter_global_ctxt<T>(
+pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
     compiler: &Compiler,
-    krate: rustc_ast::Crate,
-    f: impl for<'tcx> FnOnce(TyCtxt<'tcx>) -> T,
-) -> T {
-    let gcx_cell = OnceLock::new();
-    let arena = WorkerLocal::new(|_| Arena::default());
-    let hir_arena = WorkerLocal::new(|_| rustc_hir::Arena::default());
-
-    create_and_enter_global_ctxt_inner(compiler, krate, &gcx_cell, &arena, &hir_arena, f)
-}
-
-fn create_and_enter_global_ctxt_inner<'tcx, T>(
-    compiler: &'tcx Compiler,
     mut krate: rustc_ast::Crate,
-    gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
-    arena: &'tcx WorkerLocal<Arena<'tcx>>,
-    hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
-    f: impl FnOnce(TyCtxt<'tcx>) -> T,
+    f: F,
 ) -> T {
     let sess = &compiler.sess;
 
@@ -776,8 +761,25 @@ fn create_and_enter_global_ctxt_inner<'tcx, T>(
 
     let incremental = dep_graph.is_fully_enabled();
 
-    let qcx = gcx_cell.get_or_init(move || {
+    let gcx_cell = OnceLock::new();
+    let arena = WorkerLocal::new(|_| Arena::default());
+    let hir_arena = WorkerLocal::new(|_| rustc_hir::Arena::default());
+
+    // This closure is necessary to force rustc to perform the correct lifetime
+    // subtyping for GlobalCtxt::enter to be allowed.
+    let inner: Box<
+        dyn for<'tcx> FnOnce(
+            &'tcx Compiler,
+            &'tcx OnceLock<GlobalCtxt<'tcx>>,
+            &'tcx WorkerLocal<Arena<'tcx>>,
+            &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
+            F,
+        ) -> T,
+    > = Box::new(move |compiler, gcx_cell, arena, hir_arena, f| {
+        let sess = &compiler.sess;
+
         TyCtxt::create_global_ctxt(
+            gcx_cell,
             sess,
             crate_types,
             stable_crate_id,
@@ -794,28 +796,29 @@ fn create_and_enter_global_ctxt_inner<'tcx, T>(
             ),
             providers.hooks,
             compiler.current_gcx.clone(),
+            |tcx| {
+                let feed = tcx.create_crate_num(stable_crate_id).unwrap();
+                assert_eq!(feed.key(), LOCAL_CRATE);
+                feed.crate_name(crate_name);
+
+                let feed = tcx.feed_unit_query();
+                feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
+                    sess,
+                    &pre_configured_attrs,
+                    crate_name,
+                )));
+                feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
+                feed.output_filenames(Arc::new(outputs));
+
+                let res = f(tcx);
+                // FIXME maybe run finish even when a fatal error occured? or at least tcx.alloc_self_profile_query_strings()?
+                tcx.finish();
+                res
+            },
         )
     });
 
-    qcx.enter(|tcx| {
-        let feed = tcx.create_crate_num(stable_crate_id).unwrap();
-        assert_eq!(feed.key(), LOCAL_CRATE);
-        feed.crate_name(crate_name);
-
-        let feed = tcx.feed_unit_query();
-        feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
-            sess,
-            &pre_configured_attrs,
-            crate_name,
-        )));
-        feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
-        feed.output_filenames(Arc::new(outputs));
-
-        let res = f(tcx);
-        // FIXME maybe run finish even when a fatal error occured? or at least tcx.alloc_self_profile_query_strings()?
-        tcx.finish();
-        res
-    })
+    inner(compiler, &gcx_cell, &arena, &hir_arena, f)
 }
 
 /// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 29cf2e874a8..790b5b1a5f5 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -10,6 +10,7 @@ use std::cmp::Ordering;
 use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
 use std::ops::{Bound, Deref};
+use std::sync::OnceLock;
 use std::{fmt, iter, mem};
 
 use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
@@ -1347,33 +1348,6 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Stores memory for globals (statics/consts).
     pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
-
-    current_gcx: CurrentGcx,
-}
-
-impl<'tcx> GlobalCtxt<'tcx> {
-    /// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of
-    /// `f`.
-    pub fn enter<F, R>(&'tcx self, f: F) -> R
-    where
-        F: FnOnce(TyCtxt<'tcx>) -> R,
-    {
-        let icx = tls::ImplicitCtxt::new(self);
-
-        // Reset `current_gcx` to `None` when we exit.
-        let _on_drop = defer(move || {
-            *self.current_gcx.value.write() = None;
-        });
-
-        // Set this `GlobalCtxt` as the current one.
-        {
-            let mut guard = self.current_gcx.value.write();
-            assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
-            *guard = Some(self as *const _ as *const ());
-        }
-
-        tls::enter_context(&icx, || f(icx.tcx))
-    }
 }
 
 /// This is used to get a reference to a `GlobalCtxt` if one is available.
@@ -1517,7 +1491,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// By only providing the `TyCtxt` inside of the closure we enforce that the type
     /// context and any interned value (types, args, etc.) can only be used while `ty::tls`
     /// has a valid reference to the context, to allow formatting values that need it.
-    pub fn create_global_ctxt(
+    pub fn create_global_ctxt<T>(
+        gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
         s: &'tcx Session,
         crate_types: Vec<CrateType>,
         stable_crate_id: StableCrateId,
@@ -1529,7 +1504,8 @@ impl<'tcx> TyCtxt<'tcx> {
         query_system: QuerySystem<'tcx>,
         hooks: crate::hooks::Providers,
         current_gcx: CurrentGcx,
-    ) -> GlobalCtxt<'tcx> {
+        f: impl FnOnce(TyCtxt<'tcx>) -> T,
+    ) -> T {
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.dcx().emit_fatal(err);
         });
@@ -1538,7 +1514,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types, s, &untracked);
 
-        GlobalCtxt {
+        let gcx = gcx_cell.get_or_init(|| GlobalCtxt {
             sess: s,
             crate_types,
             stable_crate_id,
@@ -1562,8 +1538,23 @@ impl<'tcx> TyCtxt<'tcx> {
             canonical_param_env_cache: Default::default(),
             data_layout,
             alloc_map: Lock::new(interpret::AllocMap::new()),
-            current_gcx,
+        });
+
+        let icx = tls::ImplicitCtxt::new(&gcx);
+
+        // Reset `current_gcx` to `None` when we exit.
+        let _on_drop = defer(|| {
+            *current_gcx.value.write() = None;
+        });
+
+        // Set this `GlobalCtxt` as the current one.
+        {
+            let mut guard = current_gcx.value.write();
+            assert!(guard.is_none(), "no `GlobalCtxt` is currently set");
+            *guard = Some(&gcx as *const _ as *const ());
         }
+
+        tls::enter_context(&icx, || f(icx.tcx))
     }
 
     /// Obtain all lang items of this crate and all dependencies (recursively)