@@ -11,8 +11,9 @@ use crate::ty::subst::{Substs, Subst, Kind, UnpackedKind};
1111use crate :: ty:: { self , AdtDef , TypeFlags , Ty , TyCtxt , TypeFoldable } ;
1212use crate :: ty:: { List , TyS , ParamEnvAnd , ParamEnv } ;
1313use crate :: util:: captures:: Captures ;
14- use crate :: mir:: interpret:: { Scalar , Pointer } ;
14+ use crate :: mir:: interpret:: { Scalar , Pointer , Allocation } ;
1515
16+ use std:: hash:: { Hash , Hasher } ;
1617use smallvec:: SmallVec ;
1718use std:: iter;
1819use std:: cmp:: Ordering ;
@@ -2065,7 +2066,7 @@ pub enum LazyConst<'tcx> {
20652066}
20662067
20672068#[ 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 ) ;
20692070
20702071impl < ' tcx > LazyConst < ' tcx > {
20712072 pub fn map_evaluated < R > ( self , f : impl FnOnce ( Const < ' tcx > ) -> Option < R > ) -> Option < R > {
@@ -2086,15 +2087,68 @@ impl<'tcx> LazyConst<'tcx> {
20862087}
20872088
20882089/// 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 ) ]
20902091pub struct Const < ' tcx > {
20912092 pub ty : Ty < ' tcx > ,
20922093
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+ }
20942148}
20952149
20962150#[ 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 ) ;
20982152
20992153impl < ' tcx > Const < ' tcx > {
21002154 #[ inline]
@@ -2105,6 +2159,7 @@ impl<'tcx> Const<'tcx> {
21052159 Self {
21062160 val : ConstValue :: Scalar ( val) ,
21072161 ty,
2162+ alloc : None ,
21082163 }
21092164 }
21102165
0 commit comments