@@ -40,6 +40,7 @@ use rustc_hir::Node;
40
40
use rustc_index:: vec:: IndexVec ;
41
41
use rustc_macros:: HashStable ;
42
42
use rustc_query_system:: ich:: StableHashingContext ;
43
+ use rustc_serialize:: { Decodable , Encodable } ;
43
44
use rustc_span:: hygiene:: MacroKind ;
44
45
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
45
46
use rustc_span:: { ExpnId , Span } ;
@@ -49,6 +50,9 @@ pub use vtable::*;
49
50
50
51
use std:: fmt:: Debug ;
51
52
use std:: hash:: { Hash , Hasher } ;
53
+ use std:: marker:: PhantomData ;
54
+ use std:: mem;
55
+ use std:: num:: NonZeroUsize ;
52
56
use std:: ops:: ControlFlow ;
53
57
use std:: { fmt, str} ;
54
58
@@ -902,42 +906,122 @@ pub struct CoercePredicate<'tcx> {
902
906
}
903
907
pub type PolyCoercePredicate < ' tcx > = ty:: Binder < ' tcx , CoercePredicate < ' tcx > > ;
904
908
905
- #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , PartialOrd , Ord , TyEncodable , TyDecodable ) ]
906
- #[ derive( HashStable , TypeFoldable , TypeVisitable ) ]
907
- pub enum Term < ' tcx > {
908
- Ty ( Ty < ' tcx > ) ,
909
- Const ( Const < ' tcx > ) ,
909
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
910
+ pub struct Term < ' tcx > {
911
+ ptr : NonZeroUsize ,
912
+ marker : PhantomData < ( Ty < ' tcx > , Const < ' tcx > ) > ,
910
913
}
911
914
912
915
impl < ' tcx > From < Ty < ' tcx > > for Term < ' tcx > {
913
916
fn from ( ty : Ty < ' tcx > ) -> Self {
914
- Term :: Ty ( ty)
917
+ TermKind :: Ty ( ty) . pack ( )
915
918
}
916
919
}
917
920
918
921
impl < ' tcx > From < Const < ' tcx > > for Term < ' tcx > {
919
922
fn from ( c : Const < ' tcx > ) -> Self {
920
- Term :: Const ( c)
923
+ TermKind :: Const ( c) . pack ( )
924
+ }
925
+ }
926
+
927
+ impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for Term < ' tcx > {
928
+ fn hash_stable ( & self , hcx : & mut StableHashingContext < ' a > , hasher : & mut StableHasher ) {
929
+ self . unpack ( ) . hash_stable ( hcx, hasher) ;
930
+ }
931
+ }
932
+
933
+ impl < ' tcx > TypeFoldable < ' tcx > for Term < ' tcx > {
934
+ fn try_fold_with < F : FallibleTypeFolder < ' tcx > > ( self , folder : & mut F ) -> Result < Self , F :: Error > {
935
+ Ok ( self . unpack ( ) . try_fold_with ( folder) ?. pack ( ) )
936
+ }
937
+ }
938
+
939
+ impl < ' tcx > TypeVisitable < ' tcx > for Term < ' tcx > {
940
+ fn visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> ControlFlow < V :: BreakTy > {
941
+ self . unpack ( ) . visit_with ( visitor)
942
+ }
943
+ }
944
+
945
+ impl < ' tcx , E : TyEncoder < I = TyCtxt < ' tcx > > > Encodable < E > for Term < ' tcx > {
946
+ fn encode ( & self , e : & mut E ) {
947
+ self . unpack ( ) . encode ( e)
948
+ }
949
+ }
950
+
951
+ impl < ' tcx , D : TyDecoder < I = TyCtxt < ' tcx > > > Decodable < D > for Term < ' tcx > {
952
+ fn decode ( d : & mut D ) -> Self {
953
+ let res: TermKind < ' tcx > = Decodable :: decode ( d) ;
954
+ res. pack ( )
921
955
}
922
956
}
923
957
924
958
impl < ' tcx > Term < ' tcx > {
959
+ #[ inline]
960
+ pub fn unpack ( self ) -> TermKind < ' tcx > {
961
+ let ptr = self . ptr . get ( ) ;
962
+ // SAFETY: use of `Interned::new_unchecked` here is ok because these
963
+ // pointers were originally created from `Interned` types in `pack()`,
964
+ // and this is just going in the other direction.
965
+ unsafe {
966
+ match ptr & TAG_MASK {
967
+ TYPE_TAG => TermKind :: Ty ( Ty ( Interned :: new_unchecked (
968
+ & * ( ( ptr & !TAG_MASK ) as * const WithStableHash < ty:: TyS < ' tcx > > ) ,
969
+ ) ) ) ,
970
+ CONST_TAG => TermKind :: Const ( ty:: Const ( Interned :: new_unchecked (
971
+ & * ( ( ptr & !TAG_MASK ) as * const ty:: ConstS < ' tcx > ) ,
972
+ ) ) ) ,
973
+ _ => core:: intrinsics:: unreachable ( ) ,
974
+ }
975
+ }
976
+ }
977
+
925
978
pub fn ty ( & self ) -> Option < Ty < ' tcx > > {
926
- if let Term :: Ty ( ty) = self { Some ( * ty) } else { None }
979
+ if let TermKind :: Ty ( ty) = self . unpack ( ) { Some ( ty) } else { None }
927
980
}
928
981
929
982
pub fn ct ( & self ) -> Option < Const < ' tcx > > {
930
- if let Term :: Const ( c) = self { Some ( * c) } else { None }
983
+ if let TermKind :: Const ( c) = self . unpack ( ) { Some ( c) } else { None }
931
984
}
932
985
933
986
pub fn into_arg ( self ) -> GenericArg < ' tcx > {
934
- match self {
935
- Term :: Ty ( ty) => ty. into ( ) ,
936
- Term :: Const ( c) => c. into ( ) ,
987
+ match self . unpack ( ) {
988
+ TermKind :: Ty ( ty) => ty. into ( ) ,
989
+ TermKind :: Const ( c) => c. into ( ) ,
937
990
}
938
991
}
939
992
}
940
993
994
+ const TAG_MASK : usize = 0b11 ;
995
+ const TYPE_TAG : usize = 0b00 ;
996
+ const CONST_TAG : usize = 0b01 ;
997
+
998
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , PartialOrd , Ord , TyEncodable , TyDecodable ) ]
999
+ #[ derive( HashStable , TypeFoldable , TypeVisitable ) ]
1000
+ pub enum TermKind < ' tcx > {
1001
+ Ty ( Ty < ' tcx > ) ,
1002
+ Const ( Const < ' tcx > ) ,
1003
+ }
1004
+
1005
+ impl < ' tcx > TermKind < ' tcx > {
1006
+ #[ inline]
1007
+ fn pack ( self ) -> Term < ' tcx > {
1008
+ let ( tag, ptr) = match self {
1009
+ TermKind :: Ty ( ty) => {
1010
+ // Ensure we can use the tag bits.
1011
+ assert_eq ! ( mem:: align_of_val( & * ty. 0.0 ) & TAG_MASK , 0 ) ;
1012
+ ( TYPE_TAG , ty. 0 . 0 as * const WithStableHash < ty:: TyS < ' tcx > > as usize )
1013
+ }
1014
+ TermKind :: Const ( ct) => {
1015
+ // Ensure we can use the tag bits.
1016
+ assert_eq ! ( mem:: align_of_val( & * ct. 0.0 ) & TAG_MASK , 0 ) ;
1017
+ ( CONST_TAG , ct. 0 . 0 as * const ty:: ConstS < ' tcx > as usize )
1018
+ }
1019
+ } ;
1020
+
1021
+ Term { ptr : unsafe { NonZeroUsize :: new_unchecked ( ptr | tag) } , marker : PhantomData }
1022
+ }
1023
+ }
1024
+
941
1025
/// This kind of predicate has no *direct* correspondent in the
942
1026
/// syntax, but it roughly corresponds to the syntactic forms:
943
1027
///
@@ -2528,7 +2612,7 @@ mod size_asserts {
2528
2612
use super :: * ;
2529
2613
use rustc_data_structures:: static_assert_size;
2530
2614
// These are in alphabetical order, which is easy to maintain.
2531
- static_assert_size ! ( PredicateS <' _>, 56 ) ;
2615
+ static_assert_size ! ( PredicateS <' _>, 48 ) ;
2532
2616
static_assert_size ! ( TyS <' _>, 40 ) ;
2533
2617
static_assert_size ! ( WithStableHash <TyS <' _>>, 56 ) ;
2534
2618
}
0 commit comments