Skip to content

Commit db168bc

Browse files
committed
Fix equality check for constants
1 parent f5fb34c commit db168bc

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

src/librustc/ty/sty.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
1313
use crate::util::captures::Captures;
1414
use crate::mir::interpret::{Scalar, Pointer, Allocation};
1515

16+
use std::hash::{Hash, Hasher};
1617
use smallvec::SmallVec;
1718
use std::iter;
1819
use std::cmp::Ordering;
@@ -2086,7 +2087,7 @@ 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)]
20902091
pub struct Const<'tcx> {
20912092
pub ty: Ty<'tcx>,
20922093

@@ -2104,6 +2105,46 @@ pub struct Const<'tcx> {
21042105
pub alloc: Option<(&'tcx Allocation, Pointer)>,
21052106
}
21062107

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+
if let ConstValue::ByRef = val {
2136+
let (alloc, ptr) = alloc.unwrap();
2137+
// type check for future changes
2138+
let alloc: &'tcx Allocation = alloc;
2139+
alloc.hash(hasher);
2140+
ptr.offset.hash(hasher);
2141+
// do not hash the alloc id in the pointer. It does not add anything new to the hash.
2142+
// If the hash of the alloc id is the same, then the hash of the allocation would also
2143+
// be the same.
2144+
}
2145+
}
2146+
}
2147+
21072148
#[cfg(target_arch = "x86_64")]
21082149
static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 72);
21092150

0 commit comments

Comments
 (0)