@@ -41,6 +41,7 @@ use rustc_hir::Node;
41
41
use rustc_index:: vec:: IndexVec ;
42
42
use rustc_macros:: HashStable ;
43
43
use rustc_query_system:: ich:: StableHashingContext ;
44
+ use rustc_serialize:: { Decodable , Encodable } ;
44
45
use rustc_span:: hygiene:: MacroKind ;
45
46
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
46
47
use rustc_span:: { ExpnId , Span } ;
@@ -50,6 +51,9 @@ pub use vtable::*;
50
51
51
52
use std:: fmt:: Debug ;
52
53
use std:: hash:: { Hash , Hasher } ;
54
+ use std:: marker:: PhantomData ;
55
+ use std:: mem;
56
+ use std:: num:: NonZeroUsize ;
53
57
use std:: ops:: ControlFlow ;
54
58
use std:: { fmt, str} ;
55
59
@@ -459,15 +463,6 @@ pub(crate) struct TyS<'tcx> {
459
463
outer_exclusive_binder : ty:: DebruijnIndex ,
460
464
}
461
465
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
-
471
466
/// Use this rather than `TyS`, whenever possible.
472
467
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash , HashStable ) ]
473
468
#[ rustc_diagnostic_item = "Ty" ]
@@ -524,10 +519,6 @@ pub(crate) struct PredicateS<'tcx> {
524
519
outer_exclusive_binder : ty:: DebruijnIndex ,
525
520
}
526
521
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
-
531
522
/// Use this rather than `PredicateS`, whenever possible.
532
523
#[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
533
524
#[ rustc_pass_by_value]
@@ -911,42 +902,122 @@ pub struct CoercePredicate<'tcx> {
911
902
}
912
903
pub type PolyCoercePredicate < ' tcx > = ty:: Binder < ' tcx , CoercePredicate < ' tcx > > ;
913
904
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 > ) > ,
919
909
}
920
910
921
911
impl < ' tcx > From < Ty < ' tcx > > for Term < ' tcx > {
922
912
fn from ( ty : Ty < ' tcx > ) -> Self {
923
- Term :: Ty ( ty)
913
+ TermKind :: Ty ( ty) . pack ( )
924
914
}
925
915
}
926
916
927
917
impl < ' tcx > From < Const < ' tcx > > for Term < ' tcx > {
928
918
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 ( )
930
951
}
931
952
}
932
953
933
954
impl < ' 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
+
934
974
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 }
936
976
}
937
977
938
978
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 }
940
980
}
941
981
942
982
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 ( ) ,
946
986
}
947
987
}
948
988
}
949
989
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
+
950
1021
/// This kind of predicate has no *direct* correspondent in the
951
1022
/// syntax, but it roughly corresponds to the syntactic forms:
952
1023
///
@@ -2531,3 +2602,14 @@ pub struct DestructuredConst<'tcx> {
2531
2602
pub variant : Option < VariantIdx > ,
2532
2603
pub fields : & ' tcx [ ty:: Const < ' tcx > ] ,
2533
2604
}
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