1+ // ignore-tidy-filelength
2+
13pub use self :: fold:: { TypeFoldable , TypeVisitor } ;
24pub use self :: AssocItemContainer :: * ;
35pub use self :: BorrowKind :: * ;
@@ -45,6 +47,7 @@ use std::cell::RefCell;
4547use std:: cmp:: Ordering ;
4648use std:: fmt;
4749use std:: hash:: { Hash , Hasher } ;
50+ use std:: marker:: PhantomData ;
4851use std:: ops:: Range ;
4952use std:: ptr;
5053
@@ -1571,24 +1574,92 @@ pub type PlaceholderConst = Placeholder<BoundVar>;
15711574/// When type checking, we use the `ParamEnv` to track
15721575/// details about the set of where-clauses that are in scope at this
15731576/// particular point.
1574- #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash , HashStable , TypeFoldable ) ]
1577+ #[ derive( Copy , Clone ) ]
15751578pub struct ParamEnv < ' tcx > {
1579+ // We pack the caller_bounds List pointer and a Reveal enum into this usize.
1580+ // Specifically, the low bit represents Reveal, with 0 meaning `UserFacing`
1581+ // and 1 meaning `All`. The rest is the pointer.
1582+ //
1583+ // This relies on the List<ty::Predicate<'tcx>> type having at least 2-byte
1584+ // alignment. Lists start with a usize and are repr(C) so this should be
1585+ // fine; there is a debug_assert in the constructor as well.
1586+ //
1587+ // Note that the choice of 0 for UserFacing is intentional -- since it is the
1588+ // first variant in Reveal this means that joining the pointer is a simple `or`.
1589+ packed_data : usize ,
1590+
15761591 /// `Obligation`s that the caller must satisfy. This is basically
15771592 /// the set of bounds on the in-scope type parameters, translated
15781593 /// into `Obligation`s, and elaborated and normalized.
1579- pub caller_bounds : & ' tcx List < ty:: Predicate < ' tcx > > ,
1594+ ///
1595+ /// Note: This is packed into the `packed_data` usize above, use the
1596+ /// `caller_bounds()` method to access it.
1597+ caller_bounds : PhantomData < & ' tcx List < ty:: Predicate < ' tcx > > > ,
15801598
15811599 /// Typically, this is `Reveal::UserFacing`, but during codegen we
1582- /// want `Reveal::All` -- note that this is always paired with an
1583- /// empty environment. To get that, use `ParamEnv::reveal()`.
1584- pub reveal : traits:: Reveal ,
1600+ /// want `Reveal::All`.
1601+ ///
1602+ /// Note: This is packed into the caller_bounds usize above, use the reveal()
1603+ /// method to access it.
1604+ reveal : PhantomData < traits:: Reveal > ,
15851605
15861606 /// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`,
15871607 /// register that `def_id` (useful for transitioning to the chalk trait
15881608 /// solver).
15891609 pub def_id : Option < DefId > ,
15901610}
15911611
1612+ impl < ' tcx > fmt:: Debug for ParamEnv < ' tcx > {
1613+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1614+ f. debug_struct ( "ParamEnv" )
1615+ . field ( "caller_bounds" , & self . caller_bounds ( ) )
1616+ . field ( "reveal" , & self . reveal ( ) )
1617+ . field ( "def_id" , & self . def_id )
1618+ . finish ( )
1619+ }
1620+ }
1621+
1622+ impl < ' tcx > Hash for ParamEnv < ' tcx > {
1623+ fn hash < H : Hasher > ( & self , state : & mut H ) {
1624+ self . caller_bounds ( ) . hash ( state) ;
1625+ self . reveal ( ) . hash ( state) ;
1626+ self . def_id . hash ( state) ;
1627+ }
1628+ }
1629+
1630+ impl < ' tcx > PartialEq for ParamEnv < ' tcx > {
1631+ fn eq ( & self , other : & Self ) -> bool {
1632+ self . caller_bounds ( ) == other. caller_bounds ( )
1633+ && self . reveal ( ) == other. reveal ( )
1634+ && self . def_id == other. def_id
1635+ }
1636+ }
1637+ impl < ' tcx > Eq for ParamEnv < ' tcx > { }
1638+
1639+ impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for ParamEnv < ' tcx > {
1640+ fn hash_stable ( & self , hcx : & mut StableHashingContext < ' a > , hasher : & mut StableHasher ) {
1641+ self . caller_bounds ( ) . hash_stable ( hcx, hasher) ;
1642+ self . reveal ( ) . hash_stable ( hcx, hasher) ;
1643+ self . def_id . hash_stable ( hcx, hasher) ;
1644+ }
1645+ }
1646+
1647+ impl < ' tcx > TypeFoldable < ' tcx > for ParamEnv < ' tcx > {
1648+ fn super_fold_with < F : ty:: fold:: TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
1649+ ParamEnv :: new (
1650+ self . caller_bounds ( ) . fold_with ( folder) ,
1651+ self . reveal ( ) . fold_with ( folder) ,
1652+ self . def_id . fold_with ( folder) ,
1653+ )
1654+ }
1655+
1656+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
1657+ self . caller_bounds ( ) . visit_with ( visitor)
1658+ || self . reveal ( ) . visit_with ( visitor)
1659+ || self . def_id . visit_with ( visitor)
1660+ }
1661+ }
1662+
15921663impl < ' tcx > ParamEnv < ' tcx > {
15931664 /// Construct a trait environment suitable for contexts where
15941665 /// there are no where-clauses in scope. Hidden types (like `impl
@@ -1599,6 +1670,17 @@ impl<'tcx> ParamEnv<'tcx> {
15991670 Self :: new ( List :: empty ( ) , Reveal :: UserFacing , None )
16001671 }
16011672
1673+ #[ inline]
1674+ pub fn caller_bounds ( self ) -> & ' tcx List < ty:: Predicate < ' tcx > > {
1675+ // mask out bottom bit
1676+ unsafe { & * ( ( self . packed_data & ( !1 ) ) as * const _ ) }
1677+ }
1678+
1679+ #[ inline]
1680+ pub fn reveal ( self ) -> traits:: Reveal {
1681+ if self . packed_data & 1 == 0 { traits:: Reveal :: UserFacing } else { traits:: Reveal :: All }
1682+ }
1683+
16021684 /// Construct a trait environment with no where-clauses in scope
16031685 /// where the values of all `impl Trait` and other hidden types
16041686 /// are revealed. This is suitable for monomorphized, post-typeck
@@ -1618,7 +1700,25 @@ impl<'tcx> ParamEnv<'tcx> {
16181700 reveal : Reveal ,
16191701 def_id : Option < DefId > ,
16201702 ) -> Self {
1621- ty:: ParamEnv { caller_bounds, reveal, def_id }
1703+ let packed_data = caller_bounds as * const _ as usize ;
1704+ // Check that we can pack the reveal data into the pointer.
1705+ debug_assert ! ( packed_data & 1 == 0 ) ;
1706+ ty:: ParamEnv {
1707+ packed_data : packed_data
1708+ | match reveal {
1709+ Reveal :: UserFacing => 0 ,
1710+ Reveal :: All => 1 ,
1711+ } ,
1712+ caller_bounds : PhantomData ,
1713+ reveal : PhantomData ,
1714+ def_id,
1715+ }
1716+ }
1717+
1718+ pub fn with_user_facing ( mut self ) -> Self {
1719+ // clear bottom bit
1720+ self . packed_data &= !1 ;
1721+ self
16221722 }
16231723
16241724 /// Returns a new parameter environment with the same clauses, but
@@ -1627,13 +1727,14 @@ impl<'tcx> ParamEnv<'tcx> {
16271727 /// the desired behavior during codegen and certain other special
16281728 /// contexts; normally though we want to use `Reveal::UserFacing`,
16291729 /// which is the default.
1630- pub fn with_reveal_all ( self ) -> Self {
1631- ty:: ParamEnv { reveal : Reveal :: All , ..self }
1730+ pub fn with_reveal_all ( mut self ) -> Self {
1731+ self . packed_data |= 1 ;
1732+ self
16321733 }
16331734
16341735 /// Returns this same environment but with no caller bounds.
16351736 pub fn without_caller_bounds ( self ) -> Self {
1636- ty :: ParamEnv { caller_bounds : List :: empty ( ) , .. self }
1737+ Self :: new ( List :: empty ( ) , self . reveal ( ) , self . def_id )
16371738 }
16381739
16391740 /// Creates a suitable environment in which to perform trait
@@ -1649,7 +1750,7 @@ impl<'tcx> ParamEnv<'tcx> {
16491750 /// satisfiable. We generally want to behave as if they were true,
16501751 /// although the surrounding function is never reachable.
16511752 pub fn and < T : TypeFoldable < ' tcx > > ( self , value : T ) -> ParamEnvAnd < ' tcx , T > {
1652- match self . reveal {
1753+ match self . reveal ( ) {
16531754 Reveal :: UserFacing => ParamEnvAnd { param_env : self , value } ,
16541755
16551756 Reveal :: All => {
0 commit comments