@@ -10,6 +10,7 @@ use std::cmp::Ordering;
10
10
use std:: hash:: { Hash , Hasher } ;
11
11
use std:: marker:: PhantomData ;
12
12
use std:: ops:: { Bound , Deref } ;
13
+ use std:: sync:: OnceLock ;
13
14
use std:: { fmt, iter, mem} ;
14
15
15
16
use rustc_abi:: { ExternAbi , FieldIdx , Layout , LayoutData , TargetDataLayout , VariantIdx } ;
@@ -1347,33 +1348,6 @@ pub struct GlobalCtxt<'tcx> {
1347
1348
1348
1349
/// Stores memory for globals (statics/consts).
1349
1350
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
- }
1377
1351
}
1378
1352
1379
1353
/// This is used to get a reference to a `GlobalCtxt` if one is available.
@@ -1517,7 +1491,8 @@ impl<'tcx> TyCtxt<'tcx> {
1517
1491
/// By only providing the `TyCtxt` inside of the closure we enforce that the type
1518
1492
/// context and any interned value (types, args, etc.) can only be used while `ty::tls`
1519
1493
/// 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 > > ,
1521
1496
s : & ' tcx Session ,
1522
1497
crate_types : Vec < CrateType > ,
1523
1498
stable_crate_id : StableCrateId ,
@@ -1529,7 +1504,8 @@ impl<'tcx> TyCtxt<'tcx> {
1529
1504
query_system : QuerySystem < ' tcx > ,
1530
1505
hooks : crate :: hooks:: Providers ,
1531
1506
current_gcx : CurrentGcx ,
1532
- ) -> GlobalCtxt < ' tcx > {
1507
+ f : impl FnOnce ( TyCtxt < ' tcx > ) -> T ,
1508
+ ) -> T {
1533
1509
let data_layout = s. target . parse_data_layout ( ) . unwrap_or_else ( |err| {
1534
1510
s. dcx ( ) . emit_fatal ( err) ;
1535
1511
} ) ;
@@ -1538,7 +1514,7 @@ impl<'tcx> TyCtxt<'tcx> {
1538
1514
let common_lifetimes = CommonLifetimes :: new ( & interners) ;
1539
1515
let common_consts = CommonConsts :: new ( & interners, & common_types, s, & untracked) ;
1540
1516
1541
- GlobalCtxt {
1517
+ let gcx = gcx_cell . get_or_init ( || GlobalCtxt {
1542
1518
sess : s,
1543
1519
crate_types,
1544
1520
stable_crate_id,
@@ -1562,8 +1538,23 @@ impl<'tcx> TyCtxt<'tcx> {
1562
1538
canonical_param_env_cache : Default :: default ( ) ,
1563
1539
data_layout,
1564
1540
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 ( ) ) ;
1566
1555
}
1556
+
1557
+ tls:: enter_context ( & icx, || f ( icx. tcx ) )
1567
1558
}
1568
1559
1569
1560
/// Obtain all lang items of this crate and all dependencies (recursively)
0 commit comments