]> git.lizzy.rs Git - rust.git/commitdiff
Stacked Borrows: alignment does not matter
authorRalf Jung <post@ralfj.de>
Sat, 18 Apr 2020 11:56:09 +0000 (13:56 +0200)
committerRalf Jung <post@ralfj.de>
Wed, 22 Apr 2020 21:32:19 +0000 (23:32 +0200)
src/stacked_borrows.rs
tests/run-pass/packed_struct.rs

index 3412f00964b4a1934157d54e0c90da429f399b11..03140c867b2d07d19dca3025ad198de6f1bffe8d 100644 (file)
@@ -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);
         }
 
index 7aa53ef568f560c2f0d58a9f5fadfe6cfc3e0a15..5582caaf37ea5fdb9e3a9ef9033d282763384818 100644 (file)
@@ -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);