@@ -11,8 +11,9 @@ use crate::ty::subst::{Substs, Subst, Kind, UnpackedKind};
11
11
use crate :: ty:: { self , AdtDef , TypeFlags , Ty , TyCtxt , TypeFoldable } ;
12
12
use crate :: ty:: { List , TyS , ParamEnvAnd , ParamEnv } ;
13
13
use crate :: util:: captures:: Captures ;
14
- use crate :: mir:: interpret:: { Scalar , Pointer } ;
14
+ use crate :: mir:: interpret:: { Scalar , Pointer , Allocation } ;
15
15
16
+ use std:: hash:: { Hash , Hasher } ;
16
17
use smallvec:: SmallVec ;
17
18
use std:: iter;
18
19
use std:: cmp:: Ordering ;
@@ -2065,7 +2066,7 @@ pub enum LazyConst<'tcx> {
2065
2066
}
2066
2067
2067
2068
#[ cfg( target_arch = "x86_64" ) ]
2068
- static_assert ! ( LAZY_CONST_SIZE : :: std:: mem:: size_of:: <LazyConst <' static >>( ) == 56 ) ;
2069
+ static_assert ! ( LAZY_CONST_SIZE : :: std:: mem:: size_of:: <LazyConst <' static >>( ) == 80 ) ;
2069
2070
2070
2071
impl < ' tcx > LazyConst < ' tcx > {
2071
2072
pub fn map_evaluated < R > ( self , f : impl FnOnce ( Const < ' tcx > ) -> Option < R > ) -> Option < R > {
@@ -2086,15 +2087,68 @@ impl<'tcx> LazyConst<'tcx> {
2086
2087
}
2087
2088
2088
2089
/// Typed constant value.
2089
- #[ derive( Copy , Clone , Debug , Hash , RustcEncodable , RustcDecodable , Eq , PartialEq , Ord , PartialOrd ) ]
2090
+ #[ derive( Copy , Clone , Debug , RustcEncodable , RustcDecodable , Eq , Ord , PartialOrd ) ]
2090
2091
pub struct Const < ' tcx > {
2091
2092
pub ty : Ty < ' tcx > ,
2092
2093
2093
- pub val : ConstValue < ' tcx > ,
2094
+ /// This field is an optimization for caching commonly needed values of constants like `usize`
2095
+ /// (or other integers for enum discriminants) and slices (e.g. from `b"foo"` and `"foo"`
2096
+ /// literals)
2097
+ pub val : ConstValue ,
2098
+
2099
+ /// The actual backing storage of the constant and a pointer which can be resolved back to the
2100
+ /// `allocation` field
2101
+ ///
2102
+ /// Can be `None` for trivial constants created from literals or directly. Is always `Some` for
2103
+ /// aggregate constants or any named constant that you can actually end up taking a reference
2104
+ /// to. This will get unwrapped in situations where we do know that it's a referencable
2105
+ pub alloc : Option < ( & ' tcx Allocation , Pointer ) > ,
2106
+ }
2107
+
2108
+ impl < ' tcx > PartialEq for Const < ' tcx > {
2109
+ fn eq ( & self , other : & Self ) -> bool {
2110
+
2111
+ self . ty == other. ty && match ( self . val , other. val ) {
2112
+ ( ConstValue :: ByRef , ConstValue :: ByRef ) => {
2113
+ let ( a, pa) = self . alloc . unwrap ( ) ;
2114
+ let ( b, pb) = other. alloc . unwrap ( ) ;
2115
+ // only use the alloc ids to not have to compare the full allocations
2116
+ // the ids may differ if the allocation is the same
2117
+ ( pa. offset == pb. offset ) && ( pa. alloc_id == pb. alloc_id || a == b)
2118
+ } ,
2119
+ // ignore the actual allocation, just compare the values
2120
+ ( ConstValue :: Scalar ( a) , ConstValue :: Scalar ( b) ) => a == b,
2121
+ ( ConstValue :: Slice ( a, an) , ConstValue :: Slice ( b, bn) ) => an == bn && a == b,
2122
+ // if the values don't match, the consts can't be equal and the type equality should
2123
+ // have already failed, because we make the decision for non-byref solely based on the
2124
+ // type
2125
+ _ => bug ! ( "same type but different value kind in constant: {:#?} {:#?}" , self , other) ,
2126
+ }
2127
+ }
2128
+ }
2129
+
2130
+ impl < ' tcx > Hash for Const < ' tcx > {
2131
+ fn hash < H : Hasher > ( & self , hasher : & mut H ) {
2132
+ let Const { ty, val, alloc } = self ;
2133
+ ty. hash ( hasher) ;
2134
+ val. hash ( hasher) ;
2135
+ // don't hash the memory for `Scalar` and `Slice`. There's nothing to be gained
2136
+ // by it. All the relevant info is contained in the value.
2137
+ if let ConstValue :: ByRef = val {
2138
+ let ( alloc, ptr) = alloc. unwrap ( ) ;
2139
+ // type check for future changes
2140
+ let alloc: & ' tcx Allocation = alloc;
2141
+ alloc. hash ( hasher) ;
2142
+ ptr. offset . hash ( hasher) ;
2143
+ // do not hash the alloc id in the pointer. It does not add anything new to the hash.
2144
+ // If the hash of the alloc id is the same, then the hash of the allocation would also
2145
+ // be the same.
2146
+ }
2147
+ }
2094
2148
}
2095
2149
2096
2150
#[ cfg( target_arch = "x86_64" ) ]
2097
- static_assert ! ( CONST_SIZE : :: std:: mem:: size_of:: <Const <' static >>( ) == 48 ) ;
2151
+ static_assert ! ( CONST_SIZE : :: std:: mem:: size_of:: <Const <' static >>( ) == 72 ) ;
2098
2152
2099
2153
impl < ' tcx > Const < ' tcx > {
2100
2154
#[ inline]
@@ -2105,6 +2159,7 @@ impl<'tcx> Const<'tcx> {
2105
2159
Self {
2106
2160
val : ConstValue :: Scalar ( val) ,
2107
2161
ty,
2162
+ alloc : None ,
2108
2163
}
2109
2164
}
2110
2165
0 commit comments