@@ -27,6 +27,7 @@ use rustc_data_structures::fx::FxIndexMap;
27
27
use rustc_data_structures:: sorted_map:: SortedIndexMultiMap ;
28
28
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
29
29
use rustc_data_structures:: sync:: { self , par_iter, ParallelIterator } ;
30
+ use rustc_data_structures:: tagged_ptr:: CopyTaggedPtr ;
30
31
use rustc_errors:: ErrorReported ;
31
32
use rustc_hir as hir;
32
33
use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , Namespace , Res } ;
@@ -46,7 +47,6 @@ use std::cell::RefCell;
46
47
use std:: cmp:: Ordering ;
47
48
use std:: fmt;
48
49
use std:: hash:: { Hash , Hasher } ;
49
- use std:: marker:: PhantomData ;
50
50
use std:: ops:: Range ;
51
51
use std:: ptr;
52
52
use std:: str;
@@ -1713,41 +1713,45 @@ impl WithOptConstParam<DefId> {
1713
1713
/// When type checking, we use the `ParamEnv` to track
1714
1714
/// details about the set of where-clauses that are in scope at this
1715
1715
/// particular point.
1716
- #[ derive( Copy , Clone ) ]
1716
+ #[ derive( Copy , Clone , Hash , PartialEq , Eq ) ]
1717
1717
pub struct ParamEnv < ' tcx > {
1718
- // We pack the caller_bounds List pointer and a Reveal enum into this usize.
1719
- // Specifically, the low bit represents Reveal, with 0 meaning `UserFacing`
1720
- // and 1 meaning `All`. The rest is the pointer.
1721
- //
1722
- // This relies on the List<Predicate<'tcx>> type having at least 2-byte
1723
- // alignment. Lists start with a usize and are repr(C) so this should be
1724
- // fine; there is a debug_assert in the constructor as well.
1725
- //
1726
- // Note that the choice of 0 for UserFacing is intentional -- since it is the
1727
- // first variant in Reveal this means that joining the pointer is a simple `or`.
1728
- packed_data : usize ,
1729
-
1730
- /// `Obligation`s that the caller must satisfy. This is basically
1731
- /// the set of bounds on the in-scope type parameters, translated
1718
+ /// This packs both caller bounds and the reveal enum into one pointer.
1719
+ ///
1720
+ /// Caller bounds are `Obligation`s that the caller must satisfy. This is
1721
+ /// basically the set of bounds on the in-scope type parameters, translated
1732
1722
/// into `Obligation`s, and elaborated and normalized.
1733
1723
///
1734
- /// Note: This is packed into the `packed_data` usize above, use the
1735
- /// `caller_bounds()` method to access it.
1736
- caller_bounds : PhantomData < & ' tcx List < Predicate < ' tcx > > > ,
1737
-
1724
+ /// Use the `caller_bounds()` method to access.
1725
+ ///
1738
1726
/// Typically, this is `Reveal::UserFacing`, but during codegen we
1739
1727
/// want `Reveal::All`.
1740
1728
///
1741
- /// Note: This is packed into the caller_bounds usize above, use the reveal()
1742
- /// method to access it.
1743
- reveal : PhantomData < traits:: Reveal > ,
1729
+ /// Note: This is packed, use the reveal() method to access it.
1730
+ packed : CopyTaggedPtr < & ' tcx List < Predicate < ' tcx > > , traits:: Reveal , true > ,
1744
1731
1745
1732
/// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`,
1746
1733
/// register that `def_id` (useful for transitioning to the chalk trait
1747
1734
/// solver).
1748
1735
pub def_id : Option < DefId > ,
1749
1736
}
1750
1737
1738
+ unsafe impl rustc_data_structures:: tagged_ptr:: Tag for traits:: Reveal {
1739
+ const BITS : usize = 1 ;
1740
+ fn into_usize ( self ) -> usize {
1741
+ match self {
1742
+ traits:: Reveal :: UserFacing => 0 ,
1743
+ traits:: Reveal :: All => 1 ,
1744
+ }
1745
+ }
1746
+ unsafe fn from_usize ( ptr : usize ) -> Self {
1747
+ match ptr {
1748
+ 0 => traits:: Reveal :: UserFacing ,
1749
+ 1 => traits:: Reveal :: All ,
1750
+ _ => std:: hint:: unreachable_unchecked ( ) ,
1751
+ }
1752
+ }
1753
+ }
1754
+
1751
1755
impl < ' tcx > fmt:: Debug for ParamEnv < ' tcx > {
1752
1756
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1753
1757
f. debug_struct ( "ParamEnv" )
@@ -1758,24 +1762,6 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
1758
1762
}
1759
1763
}
1760
1764
1761
- impl < ' tcx > Hash for ParamEnv < ' tcx > {
1762
- fn hash < H : Hasher > ( & self , state : & mut H ) {
1763
- // List hashes as the raw pointer, so we can skip splitting into the
1764
- // pointer and the enum.
1765
- self . packed_data . hash ( state) ;
1766
- self . def_id . hash ( state) ;
1767
- }
1768
- }
1769
-
1770
- impl < ' tcx > PartialEq for ParamEnv < ' tcx > {
1771
- fn eq ( & self , other : & Self ) -> bool {
1772
- self . caller_bounds ( ) == other. caller_bounds ( )
1773
- && self . reveal ( ) == other. reveal ( )
1774
- && self . def_id == other. def_id
1775
- }
1776
- }
1777
- impl < ' tcx > Eq for ParamEnv < ' tcx > { }
1778
-
1779
1765
impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for ParamEnv < ' tcx > {
1780
1766
fn hash_stable ( & self , hcx : & mut StableHashingContext < ' a > , hasher : & mut StableHasher ) {
1781
1767
self . caller_bounds ( ) . hash_stable ( hcx, hasher) ;
@@ -1812,13 +1798,12 @@ impl<'tcx> ParamEnv<'tcx> {
1812
1798
1813
1799
#[ inline]
1814
1800
pub fn caller_bounds ( self ) -> & ' tcx List < Predicate < ' tcx > > {
1815
- // mask out bottom bit
1816
- unsafe { & * ( ( self . packed_data & ( !1 ) ) as * const _ ) }
1801
+ self . packed . pointer ( )
1817
1802
}
1818
1803
1819
1804
#[ inline]
1820
1805
pub fn reveal ( self ) -> traits:: Reveal {
1821
- if self . packed_data & 1 == 0 { traits :: Reveal :: UserFacing } else { traits :: Reveal :: All }
1806
+ self . packed . tag ( )
1822
1807
}
1823
1808
1824
1809
/// Construct a trait environment with no where-clauses in scope
@@ -1840,24 +1825,11 @@ impl<'tcx> ParamEnv<'tcx> {
1840
1825
reveal : Reveal ,
1841
1826
def_id : Option < DefId > ,
1842
1827
) -> Self {
1843
- let packed_data = caller_bounds as * const _ as usize ;
1844
- // Check that we can pack the reveal data into the pointer.
1845
- debug_assert ! ( packed_data & 1 == 0 ) ;
1846
- ty:: ParamEnv {
1847
- packed_data : packed_data
1848
- | match reveal {
1849
- Reveal :: UserFacing => 0 ,
1850
- Reveal :: All => 1 ,
1851
- } ,
1852
- caller_bounds : PhantomData ,
1853
- reveal : PhantomData ,
1854
- def_id,
1855
- }
1828
+ ty:: ParamEnv { packed : CopyTaggedPtr :: new ( caller_bounds, reveal) , def_id }
1856
1829
}
1857
1830
1858
1831
pub fn with_user_facing ( mut self ) -> Self {
1859
- // clear bottom bit
1860
- self . packed_data &= !1 ;
1832
+ self . packed . set_tag ( Reveal :: UserFacing ) ;
1861
1833
self
1862
1834
}
1863
1835
@@ -1871,7 +1843,7 @@ impl<'tcx> ParamEnv<'tcx> {
1871
1843
/// will be normalized to their underlying types.
1872
1844
/// See PR #65989 and issue #65918 for more details
1873
1845
pub fn with_reveal_all_normalized ( self , tcx : TyCtxt < ' tcx > ) -> Self {
1874
- if self . packed_data & 1 == 1 {
1846
+ if self . packed . tag ( ) == traits :: Reveal :: All {
1875
1847
return self ;
1876
1848
}
1877
1849
0 commit comments