@@ -1222,7 +1222,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
1222
1222
Lrc :: new ( StableVec :: new ( v) ) ) ;
1223
1223
}
1224
1224
1225
- tls :: enter_global ( GlobalCtxt {
1225
+ let gcx = & GlobalCtxt {
1226
1226
sess : s,
1227
1227
cstore,
1228
1228
global_arenas : & arenas. global ,
@@ -1263,7 +1263,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
1263
1263
all_traits : RefCell :: new ( None ) ,
1264
1264
tx_to_llvm_workers : tx,
1265
1265
output_filenames : Arc :: new ( output_filenames. clone ( ) ) ,
1266
- } , f)
1266
+ } ;
1267
+
1268
+ tls:: enter_global ( gcx, f)
1267
1269
}
1268
1270
1269
1271
pub fn consider_optimizing < T : Fn ( ) -> String > ( & self , msg : T ) -> bool {
@@ -1487,11 +1489,25 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
1487
1489
1488
1490
impl < ' gcx : ' tcx , ' tcx > GlobalCtxt < ' gcx > {
1489
1491
/// Call the closure with a local `TyCtxt` using the given arena.
1490
- pub fn enter_local < F , R > ( & self , arena : & ' tcx DroplessArena , f : F ) -> R
1492
+ pub fn enter_local < F , R > ( & self ,
1493
+ arena : & ' tcx DroplessArena ,
1494
+ f : F ) -> R
1491
1495
where F : for < ' a > FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
1492
1496
{
1493
1497
let interners = CtxtInterners :: new ( arena) ;
1494
- tls:: enter ( self , & interners, f)
1498
+ let tcx = TyCtxt {
1499
+ gcx : self ,
1500
+ interners : & interners,
1501
+ } ;
1502
+ ty:: tls:: with_related_context ( tcx. global_tcx ( ) , |icx| {
1503
+ let new_icx = ty:: tls:: ImplicitCtxt {
1504
+ tcx,
1505
+ query : icx. query . clone ( ) ,
1506
+ } ;
1507
+ ty:: tls:: enter_context ( & new_icx, |new_icx| {
1508
+ f ( new_icx. tcx )
1509
+ } )
1510
+ } )
1495
1511
}
1496
1512
}
1497
1513
@@ -1638,21 +1654,34 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
1638
1654
}
1639
1655
1640
1656
pub mod tls {
1641
- use super :: { CtxtInterners , GlobalCtxt , TyCtxt } ;
1657
+ use super :: { GlobalCtxt , TyCtxt } ;
1642
1658
1643
1659
use std:: cell:: Cell ;
1644
1660
use std:: fmt;
1661
+ use std:: mem;
1645
1662
use syntax_pos;
1663
+ use ty:: maps;
1664
+ use errors:: { Diagnostic , TRACK_DIAGNOSTICS } ;
1665
+ use rustc_data_structures:: OnDrop ;
1666
+ use rustc_data_structures:: sync:: Lrc ;
1667
+
1668
+ #[ derive( Clone ) ]
1669
+ pub struct ImplicitCtxt < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
1670
+ pub tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
1671
+ pub query : Option < Lrc < maps:: QueryJob < ' gcx > > > ,
1672
+ }
1673
+
1674
+ thread_local ! ( static TLV : Cell <usize > = Cell :: new( 0 ) ) ;
1646
1675
1647
- /// Marker types used for the scoped TLS slot.
1648
- /// The type context cannot be used directly because the scoped TLS
1649
- /// in libstd doesn't allow types generic over lifetimes.
1650
- enum ThreadLocalGlobalCtxt { }
1651
- enum ThreadLocalInterners { }
1676
+ fn set_tlv < F : FnOnce ( ) -> R , R > ( value : usize , f : F ) -> R {
1677
+ let old = get_tlv ( ) ;
1678
+ let _reset = OnDrop ( move || TLV . with ( |tlv| tlv. set ( old) ) ) ;
1679
+ TLV . with ( |tlv| tlv. set ( value) ) ;
1680
+ f ( )
1681
+ }
1652
1682
1653
- thread_local ! {
1654
- static TLS_TCX : Cell <Option <( * const ThreadLocalGlobalCtxt ,
1655
- * const ThreadLocalInterners ) >> = Cell :: new( None )
1683
+ fn get_tlv ( ) -> usize {
1684
+ TLV . with ( |tlv| tlv. get ( ) )
1656
1685
}
1657
1686
1658
1687
fn span_debug ( span : syntax_pos:: Span , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -1661,59 +1690,120 @@ pub mod tls {
1661
1690
} )
1662
1691
}
1663
1692
1664
- pub fn enter_global < ' gcx , F , R > ( gcx : GlobalCtxt < ' gcx > , f : F ) -> R
1665
- where F : for < ' a > FnOnce ( TyCtxt < ' a , ' gcx , ' gcx > ) -> R
1693
+ fn track_diagnostic ( diagnostic : & Diagnostic ) {
1694
+ with_context ( |context| {
1695
+ if let Some ( ref query) = context. query {
1696
+ query. diagnostics . lock ( ) . push ( diagnostic. clone ( ) ) ;
1697
+ }
1698
+ } )
1699
+ }
1700
+
1701
+ pub fn with_thread_locals < F , R > ( f : F ) -> R
1702
+ where F : FnOnce ( ) -> R
1666
1703
{
1667
1704
syntax_pos:: SPAN_DEBUG . with ( |span_dbg| {
1668
1705
let original_span_debug = span_dbg. get ( ) ;
1669
1706
span_dbg. set ( span_debug) ;
1670
- let result = enter ( & gcx, & gcx. global_interners , f) ;
1671
- span_dbg. set ( original_span_debug) ;
1672
- result
1707
+
1708
+ let _on_drop = OnDrop ( move || {
1709
+ span_dbg. set ( original_span_debug) ;
1710
+ } ) ;
1711
+
1712
+ TRACK_DIAGNOSTICS . with ( |current| {
1713
+ let original = current. get ( ) ;
1714
+ current. set ( track_diagnostic) ;
1715
+
1716
+ let _on_drop = OnDrop ( move || {
1717
+ current. set ( original) ;
1718
+ } ) ;
1719
+
1720
+ f ( )
1721
+ } )
1673
1722
} )
1674
1723
}
1675
1724
1676
- pub fn enter < ' a , ' gcx : ' tcx , ' tcx , F , R > ( gcx : & ' a GlobalCtxt < ' gcx > ,
1677
- interners : & ' a CtxtInterners < ' tcx > ,
1678
- f : F ) -> R
1679
- where F : FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
1725
+ pub fn enter_global < ' gcx , F , R > ( gcx : & GlobalCtxt < ' gcx > , f : F ) -> R
1726
+ where F : for < ' a > FnOnce ( TyCtxt < ' a , ' gcx , ' gcx > ) -> R
1680
1727
{
1681
- let gcx_ptr = gcx as * const _ as * const ThreadLocalGlobalCtxt ;
1682
- let interners_ptr = interners as * const _ as * const ThreadLocalInterners ;
1683
- TLS_TCX . with ( |tls| {
1684
- let prev = tls. get ( ) ;
1685
- tls. set ( Some ( ( gcx_ptr, interners_ptr) ) ) ;
1686
- let ret = f ( TyCtxt {
1728
+ with_thread_locals ( || {
1729
+ let tcx = TyCtxt {
1687
1730
gcx,
1688
- interners,
1689
- } ) ;
1690
- tls. set ( prev) ;
1691
- ret
1731
+ interners : & gcx. global_interners ,
1732
+ } ;
1733
+ let icx = ImplicitCtxt {
1734
+ tcx,
1735
+ query : None ,
1736
+ } ;
1737
+ enter_context ( & icx, |_| {
1738
+ f ( tcx)
1739
+ } )
1740
+ } )
1741
+ }
1742
+
1743
+ pub fn enter_context < ' a , ' gcx : ' tcx , ' tcx , F , R > ( context : & ImplicitCtxt < ' a , ' gcx , ' tcx > ,
1744
+ f : F ) -> R
1745
+ where F : FnOnce ( & ImplicitCtxt < ' a , ' gcx , ' tcx > ) -> R
1746
+ {
1747
+ set_tlv ( context as * const _ as usize , || {
1748
+ f ( & context)
1749
+ } )
1750
+ }
1751
+
1752
+ pub fn with_context_opt < F , R > ( f : F ) -> R
1753
+ where F : for <' a , ' gcx , ' tcx > FnOnce ( Option < & ImplicitCtxt < ' a , ' gcx , ' tcx > > ) -> R
1754
+ {
1755
+ let context = get_tlv ( ) ;
1756
+ if context == 0 {
1757
+ f ( None )
1758
+ } else {
1759
+ unsafe { f ( Some ( & * ( context as * const ImplicitCtxt ) ) ) }
1760
+ }
1761
+ }
1762
+
1763
+ pub fn with_fully_related_context < ' a , ' gcx , ' tcx , F , R > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > , f : F ) -> R
1764
+ where F : for < ' b > FnOnce ( & ImplicitCtxt < ' b , ' gcx , ' tcx > ) -> R
1765
+ {
1766
+ with_context ( |context| {
1767
+ unsafe {
1768
+ let gcx = tcx. gcx as * const _ as usize ;
1769
+ let interners = tcx. interners as * const _ as usize ;
1770
+ assert ! ( context. tcx. gcx as * const _ as usize == gcx) ;
1771
+ assert ! ( context. tcx. interners as * const _ as usize == interners) ;
1772
+ let context: & ImplicitCtxt = mem:: transmute ( context) ;
1773
+ f ( context)
1774
+ }
1692
1775
} )
1693
1776
}
1694
1777
1778
+ pub fn with_related_context < ' a , ' gcx , ' tcx1 , F , R > ( tcx : TyCtxt < ' a , ' gcx , ' tcx1 > , f : F ) -> R
1779
+ where F : for <' b , ' tcx2 > FnOnce ( & ImplicitCtxt < ' b , ' gcx , ' tcx2 > ) -> R
1780
+ {
1781
+ with_context ( |context| {
1782
+ unsafe {
1783
+ let gcx = tcx. gcx as * const _ as usize ;
1784
+ assert ! ( context. tcx. gcx as * const _ as usize == gcx) ;
1785
+ let context: & ImplicitCtxt = mem:: transmute ( context) ;
1786
+ f ( context)
1787
+ }
1788
+ } )
1789
+ }
1790
+
1791
+ pub fn with_context < F , R > ( f : F ) -> R
1792
+ where F : for <' a , ' gcx , ' tcx > FnOnce ( & ImplicitCtxt < ' a , ' gcx , ' tcx > ) -> R
1793
+ {
1794
+ with_context_opt ( |opt_context| f ( opt_context. expect ( "no ImplicitCtxt stored in tls" ) ) )
1795
+ }
1796
+
1695
1797
pub fn with < F , R > ( f : F ) -> R
1696
1798
where F : for <' a , ' gcx , ' tcx > FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
1697
1799
{
1698
- TLS_TCX . with ( |tcx| {
1699
- let ( gcx, interners) = tcx. get ( ) . unwrap ( ) ;
1700
- let gcx = unsafe { & * ( gcx as * const GlobalCtxt ) } ;
1701
- let interners = unsafe { & * ( interners as * const CtxtInterners ) } ;
1702
- f ( TyCtxt {
1703
- gcx,
1704
- interners,
1705
- } )
1706
- } )
1800
+ with_context ( |context| f ( context. tcx ) )
1707
1801
}
1708
1802
1709
1803
pub fn with_opt < F , R > ( f : F ) -> R
1710
1804
where F : for <' a , ' gcx , ' tcx > FnOnce ( Option < TyCtxt < ' a , ' gcx , ' tcx > > ) -> R
1711
1805
{
1712
- if TLS_TCX . with ( |tcx| tcx. get ( ) . is_some ( ) ) {
1713
- with ( |v| f ( Some ( v) ) )
1714
- } else {
1715
- f ( None )
1716
- }
1806
+ with_context_opt ( |opt_context| f ( opt_context. map ( |context| context. tcx ) ) )
1717
1807
}
1718
1808
}
1719
1809
0 commit comments