@@ -1489,10 +1489,13 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
1489
1489
1490
1490
impl < ' gcx : ' tcx , ' tcx > GlobalCtxt < ' gcx > {
1491
1491
/// Call the closure with a local `TyCtxt` using the given arena.
1492
- pub fn enter_local < F , R > ( & self ,
1493
- arena : & ' tcx DroplessArena ,
1494
- f : F ) -> R
1495
- where F : for < ' a > FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
1492
+ pub fn enter_local < F , R > (
1493
+ & self ,
1494
+ arena : & ' tcx DroplessArena ,
1495
+ f : F
1496
+ ) -> R
1497
+ where
1498
+ F : for < ' a > FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
1496
1499
{
1497
1500
let interners = CtxtInterners :: new ( arena) ;
1498
1501
let tcx = TyCtxt {
@@ -1665,12 +1668,23 @@ pub mod tls {
1665
1668
use rustc_data_structures:: OnDrop ;
1666
1669
use rustc_data_structures:: sync:: Lrc ;
1667
1670
1671
+ /// This is the implicit state of rustc. It contains the current
1672
+ /// TyCtxt and query. It is updated when creating a local interner or
1673
+ /// executing a new query. Whenever there's a TyCtxt value available
1674
+ /// you should also have access to an ImplicitCtxt through the functions
1675
+ /// in this module.
1668
1676
#[ derive( Clone ) ]
1669
1677
pub struct ImplicitCtxt < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
1678
+ /// The current TyCtxt. Initially created by `enter_global` and updated
1679
+ /// by `enter_local` with a new local interner
1670
1680
pub tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
1681
+
1682
+ /// The current query job, if any. This is updated by start_job in
1683
+ /// ty::maps::plumbing when executing a query
1671
1684
pub query : Option < Lrc < maps:: QueryJob < ' gcx > > > ,
1672
1685
}
1673
1686
1687
+ // A thread local value which stores a pointer to the current ImplicitCtxt
1674
1688
thread_local ! ( static TLV : Cell <usize > = Cell :: new( 0 ) ) ;
1675
1689
1676
1690
fn set_tlv < F : FnOnce ( ) -> R , R > ( value : usize , f : F ) -> R {
@@ -1684,12 +1698,17 @@ pub mod tls {
1684
1698
TLV . with ( |tlv| tlv. get ( ) )
1685
1699
}
1686
1700
1701
+ /// This is a callback from libsyntax as it cannot access the implicit state
1702
+ /// in librustc otherwise
1687
1703
fn span_debug ( span : syntax_pos:: Span , f : & mut fmt:: Formatter ) -> fmt:: Result {
1688
1704
with ( |tcx| {
1689
1705
write ! ( f, "{}" , tcx. sess. codemap( ) . span_to_string( span) )
1690
1706
} )
1691
1707
}
1692
1708
1709
+ /// This is a callback from libsyntax as it cannot access the implicit state
1710
+ /// in librustc otherwise. It is used to when diagnostic messages are
1711
+ /// emitted and stores them in the current query, if there is one.
1693
1712
fn track_diagnostic ( diagnostic : & Diagnostic ) {
1694
1713
with_context ( |context| {
1695
1714
if let Some ( ref query) = context. query {
@@ -1698,6 +1717,7 @@ pub mod tls {
1698
1717
} )
1699
1718
}
1700
1719
1720
+ /// Sets up the callbacks from libsyntax on the current thread
1701
1721
pub fn with_thread_locals < F , R > ( f : F ) -> R
1702
1722
where F : FnOnce ( ) -> R
1703
1723
{
@@ -1722,6 +1742,20 @@ pub mod tls {
1722
1742
} )
1723
1743
}
1724
1744
1745
+ /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f`
1746
+ pub fn enter_context < ' a , ' gcx : ' tcx , ' tcx , F , R > ( context : & ImplicitCtxt < ' a , ' gcx , ' tcx > ,
1747
+ f : F ) -> R
1748
+ where F : FnOnce ( & ImplicitCtxt < ' a , ' gcx , ' tcx > ) -> R
1749
+ {
1750
+ set_tlv ( context as * const _ as usize , || {
1751
+ f ( & context)
1752
+ } )
1753
+ }
1754
+
1755
+ /// Enters GlobalCtxt by setting up libsyntax callbacks and
1756
+ /// creating a initial TyCtxt and ImplicitCtxt.
1757
+ /// This happens once per rustc session and TyCtxts only exists
1758
+ /// inside the `f` function.
1725
1759
pub fn enter_global < ' gcx , F , R > ( gcx : & GlobalCtxt < ' gcx > , f : F ) -> R
1726
1760
where F : for < ' a > FnOnce ( TyCtxt < ' a , ' gcx , ' gcx > ) -> R
1727
1761
{
@@ -1740,15 +1774,7 @@ pub mod tls {
1740
1774
} )
1741
1775
}
1742
1776
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
-
1777
+ /// Allows access to the current ImplicitCtxt in a closure if one is available
1752
1778
pub fn with_context_opt < F , R > ( f : F ) -> R
1753
1779
where F : for <' a , ' gcx , ' tcx > FnOnce ( Option < & ImplicitCtxt < ' a , ' gcx , ' tcx > > ) -> R
1754
1780
{
@@ -1760,46 +1786,62 @@ pub mod tls {
1760
1786
}
1761
1787
}
1762
1788
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
1789
+ /// Allows access to the current ImplicitCtxt.
1790
+ /// Panics if there is no ImplicitCtxt available
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
+
1797
+ /// Allows access to the current ImplicitCtxt whose tcx field has the same global
1798
+ /// interner as the tcx argument passed in. This means the closure is given an ImplicitCtxt
1799
+ /// with the same 'gcx lifetime as the TyCtxt passed in.
1800
+ /// This will panic if you pass it a TyCtxt which has a different global interner from
1801
+ /// the current ImplicitCtxt's tcx field.
1802
+ pub fn with_related_context < ' a , ' gcx , ' tcx1 , F , R > ( tcx : TyCtxt < ' a , ' gcx , ' tcx1 > , f : F ) -> R
1803
+ where F : for <' b , ' tcx2 > FnOnce ( & ImplicitCtxt < ' b , ' gcx , ' tcx2 > ) -> R
1765
1804
{
1766
1805
with_context ( |context| {
1767
1806
unsafe {
1768
1807
let gcx = tcx. gcx as * const _ as usize ;
1769
- let interners = tcx. interners as * const _ as usize ;
1770
1808
assert ! ( context. tcx. gcx as * const _ as usize == gcx) ;
1771
- assert ! ( context. tcx. interners as * const _ as usize == interners) ;
1772
1809
let context: & ImplicitCtxt = mem:: transmute ( context) ;
1773
1810
f ( context)
1774
1811
}
1775
1812
} )
1776
1813
}
1777
1814
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
1815
+ /// Allows access to the current ImplicitCtxt whose tcx field has the same global
1816
+ /// interner and local interner as the tcx argument passed in. This means the closure
1817
+ /// is given an ImplicitCtxt with the same 'tcx and 'gcx lifetimes as the TyCtxt passed in.
1818
+ /// This will panic if you pass it a TyCtxt which has a different global interner or
1819
+ /// a different local interner from the current ImplicitCtxt's tcx field.
1820
+ pub fn with_fully_related_context < ' a , ' gcx , ' tcx , F , R > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > , f : F ) -> R
1821
+ where F : for < ' b > FnOnce ( & ImplicitCtxt < ' b , ' gcx , ' tcx > ) -> R
1780
1822
{
1781
1823
with_context ( |context| {
1782
1824
unsafe {
1783
1825
let gcx = tcx. gcx as * const _ as usize ;
1826
+ let interners = tcx. interners as * const _ as usize ;
1784
1827
assert ! ( context. tcx. gcx as * const _ as usize == gcx) ;
1828
+ assert ! ( context. tcx. interners as * const _ as usize == interners) ;
1785
1829
let context: & ImplicitCtxt = mem:: transmute ( context) ;
1786
1830
f ( context)
1787
1831
}
1788
1832
} )
1789
1833
}
1790
1834
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
-
1835
+ /// Allows access to the TyCtxt in the current ImplicitCtxt.
1836
+ /// Panics if there is no ImplicitCtxt available
1797
1837
pub fn with < F , R > ( f : F ) -> R
1798
1838
where F : for <' a , ' gcx , ' tcx > FnOnce ( TyCtxt < ' a , ' gcx , ' tcx > ) -> R
1799
1839
{
1800
1840
with_context ( |context| f ( context. tcx ) )
1801
1841
}
1802
1842
1843
+ /// Allows access to the TyCtxt in the current ImplicitCtxt.
1844
+ /// The closure is passed None if there is no ImplicitCtxt available
1803
1845
pub fn with_opt < F , R > ( f : F ) -> R
1804
1846
where F : for <' a , ' gcx , ' tcx > FnOnce ( Option < TyCtxt < ' a , ' gcx , ' tcx > > ) -> R
1805
1847
{
0 commit comments