From: Ralf Jung Date: Sat, 18 Apr 2020 11:56:09 +0000 (+0200) Subject: Stacked Borrows: alignment does not matter X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=270adbc7c61a85ce8f4a3b636396b142e83b2f11;p=rust.git Stacked Borrows: alignment does not matter --- diff --git a/src/stacked_borrows.rs b/src/stacked_borrows.rs index 3412f00964b..03140c867b2 100644 --- a/src/stacked_borrows.rs +++ b/src/stacked_borrows.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::RetagKind; use rustc_middle::ty; -use rustc_target::abi::{LayoutOf, Size}; +use rustc_target::abi::{Align, LayoutOf, Size}; use rustc_hir::Mutability; use crate::*; @@ -577,11 +577,13 @@ fn retag_reference( .size_and_align_of_mplace(place)? .map(|(size, _)| size) .unwrap_or_else(|| place.layout.size); + // `reborrow` relies on getting a `Pointer` and everything being in-bounds, + // so let's ensure that. However, we do not care about alignment. // We can see dangling ptrs in here e.g. after a Box's `Unique` was - // updated using "self.0 = ..." (can happen in Box::from_raw); see miri#1050. - let place = this.mplace_access_checked(place)?; + // updated using "self.0 = ..." (can happen in Box::from_raw) so we cannot ICE; see miri#1050. + let place = this.mplace_access_checked(place, Some(Align::from_bytes(1).unwrap()))?; + // Nothing to do for ZSTs. if size == Size::ZERO { - // Nothing to do for ZSTs. return Ok(val); } diff --git a/tests/run-pass/packed_struct.rs b/tests/run-pass/packed_struct.rs index 7aa53ef568f..5582caaf37e 100644 --- a/tests/run-pass/packed_struct.rs +++ b/tests/run-pass/packed_struct.rs @@ -1,4 +1,4 @@ -#![feature(unsize, coerce_unsized)] +#![feature(unsize, coerce_unsized, raw_ref_op)] use std::collections::hash_map::DefaultHasher; use std::hash::Hash; @@ -6,6 +6,7 @@ fn test_basic() { #[repr(packed)] struct S { + fill: u8, a: i32, b: i64, } @@ -30,6 +31,7 @@ fn test(t: Test2) { } let mut x = S { + fill: 0, a: 42, b: 99, }; @@ -37,9 +39,13 @@ fn test(t: Test2) { let b = x.b; assert_eq!(a, 42); assert_eq!(b, 99); + assert_eq!(&x.fill, &0); // `fill` just requirs 1-byte-align, so this is fine // can't do `assert_eq!(x.a, 42)`, because `assert_eq!` takes a reference assert_eq!({x.a}, 42); assert_eq!({x.b}, 99); + // but we *can* take a raw pointer! + assert_eq!(unsafe { (&raw const x.a).read_unaligned() }, 42); + assert_eq!(unsafe { (&raw const x.b).read_unaligned() }, 99); x.b = 77; assert_eq!({x.b}, 77);