@@ -41,6 +41,7 @@ use rustc_hir::Node;
4141use rustc_index:: vec:: IndexVec ;
4242use rustc_macros:: HashStable ;
4343use rustc_query_system:: ich:: StableHashingContext ;
44+ use rustc_serialize:: { Decodable , Encodable } ;
4445use rustc_span:: hygiene:: MacroKind ;
4546use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
4647use rustc_span:: { ExpnId , Span } ;
@@ -50,6 +51,9 @@ pub use vtable::*;
5051
5152use std:: fmt:: Debug ;
5253use std:: hash:: { Hash , Hasher } ;
54+ use std:: marker:: PhantomData ;
55+ use std:: mem;
56+ use std:: num:: NonZeroUsize ;
5357use std:: ops:: ControlFlow ;
5458use std:: { fmt, str} ;
5559
@@ -459,15 +463,6 @@ pub(crate) struct TyS<'tcx> {
459463 outer_exclusive_binder : ty:: DebruijnIndex ,
460464}
461465
462- // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger.
463- #[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
464- static_assert_size ! ( TyS <' _>, 40 ) ;
465-
466- // We are actually storing a stable hash cache next to the type, so let's
467- // also check the full size
468- #[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
469- static_assert_size ! ( WithStableHash <TyS <' _>>, 56 ) ;
470-
471466/// Use this rather than `TyS`, whenever possible.
472467#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash , HashStable ) ]
473468#[ rustc_diagnostic_item = "Ty" ]
@@ -524,10 +519,6 @@ pub(crate) struct PredicateS<'tcx> {
524519 outer_exclusive_binder : ty:: DebruijnIndex ,
525520}
526521
527- // This type is used a lot. Make sure it doesn't unintentionally get bigger.
528- #[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
529- static_assert_size ! ( PredicateS <' _>, 56 ) ;
530-
531522/// Use this rather than `PredicateS`, whenever possible.
532523#[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
533524#[ rustc_pass_by_value]
@@ -911,42 +902,122 @@ pub struct CoercePredicate<'tcx> {
911902}
912903pub type PolyCoercePredicate < ' tcx > = ty:: Binder < ' tcx , CoercePredicate < ' tcx > > ;
913904
914- #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , PartialOrd , Ord , TyEncodable , TyDecodable ) ]
915- #[ derive( HashStable , TypeFoldable , TypeVisitable ) ]
916- pub enum Term < ' tcx > {
917- Ty ( Ty < ' tcx > ) ,
918- Const ( Const < ' tcx > ) ,
905+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
906+ pub struct Term < ' tcx > {
907+ ptr : NonZeroUsize ,
908+ marker : PhantomData < ( Ty < ' tcx > , Const < ' tcx > ) > ,
919909}
920910
921911impl < ' tcx > From < Ty < ' tcx > > for Term < ' tcx > {
922912 fn from ( ty : Ty < ' tcx > ) -> Self {
923- Term :: Ty ( ty)
913+ TermKind :: Ty ( ty) . pack ( )
924914 }
925915}
926916
927917impl < ' tcx > From < Const < ' tcx > > for Term < ' tcx > {
928918 fn from ( c : Const < ' tcx > ) -> Self {
929- Term :: Const ( c)
919+ TermKind :: Const ( c) . pack ( )
920+ }
921+ }
922+
923+ impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for Term < ' tcx > {
924+ fn hash_stable ( & self , hcx : & mut StableHashingContext < ' a > , hasher : & mut StableHasher ) {
925+ self . unpack ( ) . hash_stable ( hcx, hasher) ;
926+ }
927+ }
928+
929+ impl < ' tcx > TypeFoldable < ' tcx > for Term < ' tcx > {
930+ fn try_fold_with < F : FallibleTypeFolder < ' tcx > > ( self , folder : & mut F ) -> Result < Self , F :: Error > {
931+ Ok ( self . unpack ( ) . try_fold_with ( folder) ?. pack ( ) )
932+ }
933+ }
934+
935+ impl < ' tcx > TypeVisitable < ' tcx > for Term < ' tcx > {
936+ fn visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> ControlFlow < V :: BreakTy > {
937+ self . unpack ( ) . visit_with ( visitor)
938+ }
939+ }
940+
941+ impl < ' tcx , E : TyEncoder < I = TyCtxt < ' tcx > > > Encodable < E > for Term < ' tcx > {
942+ fn encode ( & self , e : & mut E ) {
943+ self . unpack ( ) . encode ( e)
944+ }
945+ }
946+
947+ impl < ' tcx , D : TyDecoder < I = TyCtxt < ' tcx > > > Decodable < D > for Term < ' tcx > {
948+ fn decode ( d : & mut D ) -> Self {
949+ let res: TermKind < ' tcx > = Decodable :: decode ( d) ;
950+ res. pack ( )
930951 }
931952}
932953
933954impl < ' tcx > Term < ' tcx > {
955+ #[ inline]
956+ pub fn unpack ( self ) -> TermKind < ' tcx > {
957+ let ptr = self . ptr . get ( ) ;
958+ // SAFETY: use of `Interned::new_unchecked` here is ok because these
959+ // pointers were originally created from `Interned` types in `pack()`,
960+ // and this is just going in the other direction.
961+ unsafe {
962+ match ptr & TAG_MASK {
963+ TYPE_TAG => TermKind :: Ty ( Ty ( Interned :: new_unchecked (
964+ & * ( ( ptr & !TAG_MASK ) as * const WithStableHash < ty:: TyS < ' tcx > > ) ,
965+ ) ) ) ,
966+ CONST_TAG => TermKind :: Const ( ty:: Const ( Interned :: new_unchecked (
967+ & * ( ( ptr & !TAG_MASK ) as * const ty:: ConstS < ' tcx > ) ,
968+ ) ) ) ,
969+ _ => core:: intrinsics:: unreachable ( ) ,
970+ }
971+ }
972+ }
973+
934974 pub fn ty ( & self ) -> Option < Ty < ' tcx > > {
935- if let Term :: Ty ( ty) = self { Some ( * ty) } else { None }
975+ if let TermKind :: Ty ( ty) = self . unpack ( ) { Some ( ty) } else { None }
936976 }
937977
938978 pub fn ct ( & self ) -> Option < Const < ' tcx > > {
939- if let Term :: Const ( c) = self { Some ( * c) } else { None }
979+ if let TermKind :: Const ( c) = self . unpack ( ) { Some ( c) } else { None }
940980 }
941981
942982 pub fn into_arg ( self ) -> GenericArg < ' tcx > {
943- match self {
944- Term :: Ty ( ty) => ty. into ( ) ,
945- Term :: Const ( c) => c. into ( ) ,
983+ match self . unpack ( ) {
984+ TermKind :: Ty ( ty) => ty. into ( ) ,
985+ TermKind :: Const ( c) => c. into ( ) ,
946986 }
947987 }
948988}
949989
990+ const TAG_MASK : usize = 0b11 ;
991+ const TYPE_TAG : usize = 0b00 ;
992+ const CONST_TAG : usize = 0b01 ;
993+
994+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , PartialOrd , Ord , TyEncodable , TyDecodable ) ]
995+ #[ derive( HashStable , TypeFoldable , TypeVisitable ) ]
996+ pub enum TermKind < ' tcx > {
997+ Ty ( Ty < ' tcx > ) ,
998+ Const ( Const < ' tcx > ) ,
999+ }
1000+
1001+ impl < ' tcx > TermKind < ' tcx > {
1002+ #[ inline]
1003+ fn pack ( self ) -> Term < ' tcx > {
1004+ let ( tag, ptr) = match self {
1005+ TermKind :: Ty ( ty) => {
1006+ // Ensure we can use the tag bits.
1007+ assert_eq ! ( mem:: align_of_val( & * ty. 0.0 ) & TAG_MASK , 0 ) ;
1008+ ( TYPE_TAG , ty. 0 . 0 as * const WithStableHash < ty:: TyS < ' tcx > > as usize )
1009+ }
1010+ TermKind :: Const ( ct) => {
1011+ // Ensure we can use the tag bits.
1012+ assert_eq ! ( mem:: align_of_val( & * ct. 0.0 ) & TAG_MASK , 0 ) ;
1013+ ( CONST_TAG , ct. 0 . 0 as * const ty:: ConstS < ' tcx > as usize )
1014+ }
1015+ } ;
1016+
1017+ Term { ptr : unsafe { NonZeroUsize :: new_unchecked ( ptr | tag) } , marker : PhantomData }
1018+ }
1019+ }
1020+
9501021/// This kind of predicate has no *direct* correspondent in the
9511022/// syntax, but it roughly corresponds to the syntactic forms:
9521023///
@@ -2531,3 +2602,14 @@ pub struct DestructuredConst<'tcx> {
25312602 pub variant : Option < VariantIdx > ,
25322603 pub fields : & ' tcx [ ty:: Const < ' tcx > ] ,
25332604}
2605+
2606+ // Some types are used a lot. Make sure they don't unintentionally get bigger.
2607+ #[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
2608+ mod size_asserts {
2609+ use super :: * ;
2610+ use rustc_data_structures:: static_assert_size;
2611+ // These are in alphabetical order, which is easy to maintain.
2612+ static_assert_size ! ( PredicateS <' _>, 48 ) ;
2613+ static_assert_size ! ( TyS <' _>, 40 ) ;
2614+ static_assert_size ! ( WithStableHash <TyS <' _>>, 56 ) ;
2615+ }
0 commit comments