@@ -27,6 +27,7 @@ use rustc_data_structures::fx::FxIndexMap;
2727use rustc_data_structures:: sorted_map:: SortedIndexMultiMap ;
2828use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
2929use rustc_data_structures:: sync:: { self , par_iter, ParallelIterator } ;
30+ use rustc_data_structures:: tagged_ptr:: CopyTaggedPtr ;
3031use rustc_errors:: ErrorReported ;
3132use rustc_hir as hir;
3233use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , Namespace , Res } ;
@@ -46,7 +47,6 @@ use std::cell::RefCell;
4647use std:: cmp:: Ordering ;
4748use std:: fmt;
4849use std:: hash:: { Hash , Hasher } ;
49- use std:: marker:: PhantomData ;
5050use std:: ops:: Range ;
5151use std:: ptr;
5252use std:: str;
@@ -1713,41 +1713,45 @@ impl WithOptConstParam<DefId> {
17131713/// When type checking, we use the `ParamEnv` to track
17141714/// details about the set of where-clauses that are in scope at this
17151715/// particular point.
1716- #[ derive( Copy , Clone ) ]
1716+ #[ derive( Copy , Clone , Hash , PartialEq , Eq ) ]
17171717pub 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
17321722 /// into `Obligation`s, and elaborated and normalized.
17331723 ///
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+ ///
17381726 /// Typically, this is `Reveal::UserFacing`, but during codegen we
17391727 /// want `Reveal::All`.
17401728 ///
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 > ,
17441731
17451732 /// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`,
17461733 /// register that `def_id` (useful for transitioning to the chalk trait
17471734 /// solver).
17481735 pub def_id : Option < DefId > ,
17491736}
17501737
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+
17511755impl < ' tcx > fmt:: Debug for ParamEnv < ' tcx > {
17521756 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
17531757 f. debug_struct ( "ParamEnv" )
@@ -1758,24 +1762,6 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
17581762 }
17591763}
17601764
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-
17791765impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for ParamEnv < ' tcx > {
17801766 fn hash_stable ( & self , hcx : & mut StableHashingContext < ' a > , hasher : & mut StableHasher ) {
17811767 self . caller_bounds ( ) . hash_stable ( hcx, hasher) ;
@@ -1812,13 +1798,12 @@ impl<'tcx> ParamEnv<'tcx> {
18121798
18131799 #[ inline]
18141800 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 ( )
18171802 }
18181803
18191804 #[ inline]
18201805 pub fn reveal ( self ) -> traits:: Reveal {
1821- if self . packed_data & 1 == 0 { traits :: Reveal :: UserFacing } else { traits :: Reveal :: All }
1806+ self . packed . tag ( )
18221807 }
18231808
18241809 /// Construct a trait environment with no where-clauses in scope
@@ -1840,24 +1825,11 @@ impl<'tcx> ParamEnv<'tcx> {
18401825 reveal : Reveal ,
18411826 def_id : Option < DefId > ,
18421827 ) -> 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 }
18561829 }
18571830
18581831 pub fn with_user_facing ( mut self ) -> Self {
1859- // clear bottom bit
1860- self . packed_data &= !1 ;
1832+ self . packed . set_tag ( Reveal :: UserFacing ) ;
18611833 self
18621834 }
18631835
@@ -1871,7 +1843,7 @@ impl<'tcx> ParamEnv<'tcx> {
18711843 /// will be normalized to their underlying types.
18721844 /// See PR #65989 and issue #65918 for more details
18731845 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 {
18751847 return self ;
18761848 }
18771849
0 commit comments