1
+ // ignore-tidy-filelength
2
+
1
3
pub use self :: fold:: { TypeFoldable , TypeVisitor } ;
2
4
pub use self :: AssocItemContainer :: * ;
3
5
pub use self :: BorrowKind :: * ;
@@ -45,6 +47,7 @@ use std::cell::RefCell;
45
47
use std:: cmp:: Ordering ;
46
48
use std:: fmt;
47
49
use std:: hash:: { Hash , Hasher } ;
50
+ use std:: marker:: PhantomData ;
48
51
use std:: ops:: Range ;
49
52
use std:: ptr;
50
53
@@ -1571,24 +1574,92 @@ pub type PlaceholderConst = Placeholder<BoundVar>;
1571
1574
/// When type checking, we use the `ParamEnv` to track
1572
1575
/// details about the set of where-clauses that are in scope at this
1573
1576
/// particular point.
1574
- #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash , HashStable , TypeFoldable ) ]
1577
+ #[ derive( Copy , Clone ) ]
1575
1578
pub 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
+
1576
1591
/// `Obligation`s that the caller must satisfy. This is basically
1577
1592
/// the set of bounds on the in-scope type parameters, translated
1578
1593
/// 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 > > > ,
1580
1598
1581
1599
/// 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 > ,
1585
1605
1586
1606
/// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`,
1587
1607
/// register that `def_id` (useful for transitioning to the chalk trait
1588
1608
/// solver).
1589
1609
pub def_id : Option < DefId > ,
1590
1610
}
1591
1611
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
+
1592
1663
impl < ' tcx > ParamEnv < ' tcx > {
1593
1664
/// Construct a trait environment suitable for contexts where
1594
1665
/// there are no where-clauses in scope. Hidden types (like `impl
@@ -1599,6 +1670,17 @@ impl<'tcx> ParamEnv<'tcx> {
1599
1670
Self :: new ( List :: empty ( ) , Reveal :: UserFacing , None )
1600
1671
}
1601
1672
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
+
1602
1684
/// Construct a trait environment with no where-clauses in scope
1603
1685
/// where the values of all `impl Trait` and other hidden types
1604
1686
/// are revealed. This is suitable for monomorphized, post-typeck
@@ -1618,7 +1700,25 @@ impl<'tcx> ParamEnv<'tcx> {
1618
1700
reveal : Reveal ,
1619
1701
def_id : Option < DefId > ,
1620
1702
) -> 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
1622
1722
}
1623
1723
1624
1724
/// Returns a new parameter environment with the same clauses, but
@@ -1627,13 +1727,14 @@ impl<'tcx> ParamEnv<'tcx> {
1627
1727
/// the desired behavior during codegen and certain other special
1628
1728
/// contexts; normally though we want to use `Reveal::UserFacing`,
1629
1729
/// 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
1632
1733
}
1633
1734
1634
1735
/// Returns this same environment but with no caller bounds.
1635
1736
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 )
1637
1738
}
1638
1739
1639
1740
/// Creates a suitable environment in which to perform trait
@@ -1649,7 +1750,7 @@ impl<'tcx> ParamEnv<'tcx> {
1649
1750
/// satisfiable. We generally want to behave as if they were true,
1650
1751
/// although the surrounding function is never reachable.
1651
1752
pub fn and < T : TypeFoldable < ' tcx > > ( self , value : T ) -> ParamEnvAnd < ' tcx , T > {
1652
- match self . reveal {
1753
+ match self . reveal ( ) {
1653
1754
Reveal :: UserFacing => ParamEnvAnd { param_env : self , value } ,
1654
1755
1655
1756
Reveal :: All => {
0 commit comments