Explain the use of blocks around self.data
accesses
This commit is contained in:
parent
02131f4dcd
commit
c478574786
1 changed files with 14 additions and 0 deletions
|
@ -131,6 +131,10 @@ pub struct ScalarInt {
|
||||||
// can't take references to fields of packed structs.
|
// can't take references to fields of packed structs.
|
||||||
impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
|
impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
|
||||||
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut crate::ty::StableHasher) {
|
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut crate::ty::StableHasher) {
|
||||||
|
// Using a block `{self.data}` here to force a copy instead of using `self.data`
|
||||||
|
// directly, because `hash_stable` takes `&self` and would thus borrow `self.data`.
|
||||||
|
// Since `Self` is a packed struct, that would create a possibly unaligned reference,
|
||||||
|
// which is UB on a lot of platforms.
|
||||||
{ self.data }.hash_stable(hcx, hasher);
|
{ self.data }.hash_stable(hcx, hasher);
|
||||||
self.size.hash_stable(hcx, hasher);
|
self.size.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
|
@ -167,6 +171,11 @@ impl ScalarInt {
|
||||||
/// construct `Scalar`s).
|
/// construct `Scalar`s).
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_data(self) {
|
fn check_data(self) {
|
||||||
|
// Using a block `{self.data}` here to force a copy instead of using `self.data`
|
||||||
|
// directly, because `assert_eq` takes references to its arguments and formatting
|
||||||
|
// arguments and would thus borrow `self.data`. Since `Self`
|
||||||
|
// is a packed struct, that would create a possibly unaligned reference, which
|
||||||
|
// is UB on a lot of platforms.
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
truncate(self.data, self.size()),
|
truncate(self.data, self.size()),
|
||||||
{ self.data },
|
{ self.data },
|
||||||
|
@ -336,6 +345,11 @@ impl fmt::LowerHex for ScalarInt {
|
||||||
self.check_data();
|
self.check_data();
|
||||||
// Format as hex number wide enough to fit any value of the given `size`.
|
// Format as hex number wide enough to fit any value of the given `size`.
|
||||||
// So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
|
// So data=20, size=1 will be "0x14", but with size=4 it'll be "0x00000014".
|
||||||
|
// Using a block `{self.data}` here to force a copy instead of using `self.data`
|
||||||
|
// directly, because `write!` takes references to its formatting arguments and
|
||||||
|
// would thus borrow `self.data`. Since `Self`
|
||||||
|
// is a packed struct, that would create a possibly unaligned reference, which
|
||||||
|
// is UB on a lot of platforms.
|
||||||
write!(f, "{:01$x}", { self.data }, self.size as usize * 2)
|
write!(f, "{:01$x}", { self.data }, self.size as usize * 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue