@@ -1222,7 +1222,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12221222 Lrc :: new ( StableVec :: new ( v) ) ) ;
12231223 }
12241224
1225- tls :: enter_global ( GlobalCtxt {
1225+ let gcx = & GlobalCtxt {
12261226 sess : s,
12271227 cstore,
12281228 global_arenas : & arenas. global ,
@@ -1263,7 +1263,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12631263 all_traits : RefCell :: new ( None ) ,
12641264 tx_to_llvm_workers : tx,
12651265 output_filenames : Arc :: new ( output_filenames. clone ( ) ) ,
1266- } , f)
1266+ } ;
1267+
1268+ tls:: enter_global ( gcx, f)
12671269 }
12681270
12691271 pub fn consider_optimizing < T : Fn ( ) -> String > ( & self , msg : T ) -> bool {
@@ -1487,11 +1489,25 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
14871489
14881490impl < ' gcx : ' tcx , ' tcx > GlobalCtxt < ' gcx > {
14891491 /// 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
14911495 where F : for < ' a > FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
14921496 {
14931497 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+ } )
14951511 }
14961512}
14971513
@@ -1638,21 +1654,34 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
16381654}
16391655
16401656pub mod tls {
1641- use super :: { CtxtInterners , GlobalCtxt , TyCtxt } ;
1657+ use super :: { GlobalCtxt , TyCtxt } ;
16421658
16431659 use std:: cell:: Cell ;
16441660 use std:: fmt;
1661+ use std:: mem;
16451662 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 ) ) ;
16461675
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+ }
16521682
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 ( ) )
16561685 }
16571686
16581687 fn span_debug ( span : syntax_pos:: Span , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -1661,59 +1690,120 @@ pub mod tls {
16611690 } )
16621691 }
16631692
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
16661703 {
16671704 syntax_pos:: SPAN_DEBUG . with ( |span_dbg| {
16681705 let original_span_debug = span_dbg. get ( ) ;
16691706 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+ } )
16731722 } )
16741723 }
16751724
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
16801727 {
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 {
16871730 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+ }
16921775 } )
16931776 }
16941777
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+
16951797 pub fn with < F , R > ( f : F ) -> R
16961798 where F : for <' a , ' gcx , ' tcx > FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
16971799 {
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 ) )
17071801 }
17081802
17091803 pub fn with_opt < F , R > ( f : F ) -> R
17101804 where F : for <' a , ' gcx , ' tcx > FnOnce ( Option < TyCtxt < ' a , ' gcx , ' tcx > > ) -> R
17111805 {
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 ) ) )
17171807 }
17181808}
17191809
0 commit comments