]> git.lizzy.rs Git - rust.git/commitdiff
stacked borrows is broken without full MIR
authorRalf Jung <post@ralfj.de>
Fri, 16 Nov 2018 09:01:54 +0000 (10:01 +0100)
committerRalf Jung <post@ralfj.de>
Fri, 16 Nov 2018 09:01:54 +0000 (10:01 +0100)
66 files changed:
README.md
tests/compile-fail-fullmir/copy_nonoverlapping.rs [new file with mode: 0644]
tests/compile-fail-fullmir/memleak_rc.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/alias_through_mutation.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/aliasing_mut1.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/aliasing_mut2.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/aliasing_mut3.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/aliasing_mut4.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/buggy_as_mut_slice.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/buggy_split_at_mut.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_read1.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_read2.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_read3.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_read4.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_read5.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_write1.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_write2.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_write3.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_write4.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/illegal_write5.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/load_invalid_mut.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/load_invalid_shr.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/mut_exclusive_violation1.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/outdated_local.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/pass_invalid_mut.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/pass_invalid_shr.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/pointer_smuggling.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/return_invalid_mut.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/return_invalid_shr.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/static_memory_modification.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/transmute-is-no-escape.rs [new file with mode: 0644]
tests/compile-fail-fullmir/stacked_borrows/unescaped_local.rs [new file with mode: 0644]
tests/compile-fail-fullmir/transmute-pair-undef.rs [new file with mode: 0644]
tests/compile-fail/copy_nonoverlapping.rs [deleted file]
tests/compile-fail/memleak_rc.rs [deleted file]
tests/compile-fail/stacked_borrows/alias_through_mutation.rs [deleted file]
tests/compile-fail/stacked_borrows/aliasing_mut1.rs [deleted file]
tests/compile-fail/stacked_borrows/aliasing_mut2.rs [deleted file]
tests/compile-fail/stacked_borrows/aliasing_mut3.rs [deleted file]
tests/compile-fail/stacked_borrows/aliasing_mut4.rs [deleted file]
tests/compile-fail/stacked_borrows/buggy_as_mut_slice.rs [deleted file]
tests/compile-fail/stacked_borrows/buggy_split_at_mut.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_read1.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_read2.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_read3.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_read4.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_read5.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_write1.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_write2.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_write3.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_write4.rs [deleted file]
tests/compile-fail/stacked_borrows/illegal_write5.rs [deleted file]
tests/compile-fail/stacked_borrows/load_invalid_mut.rs [deleted file]
tests/compile-fail/stacked_borrows/load_invalid_shr.rs [deleted file]
tests/compile-fail/stacked_borrows/mut_exclusive_violation1.rs [deleted file]
tests/compile-fail/stacked_borrows/outdated_local.rs [deleted file]
tests/compile-fail/stacked_borrows/pass_invalid_mut.rs [deleted file]
tests/compile-fail/stacked_borrows/pass_invalid_shr.rs [deleted file]
tests/compile-fail/stacked_borrows/pointer_smuggling.rs [deleted file]
tests/compile-fail/stacked_borrows/return_invalid_mut.rs [deleted file]
tests/compile-fail/stacked_borrows/return_invalid_shr.rs [deleted file]
tests/compile-fail/stacked_borrows/static_memory_modification.rs [deleted file]
tests/compile-fail/stacked_borrows/transmute-is-no-escape.rs [deleted file]
tests/compile-fail/stacked_borrows/unescaped_local.rs [deleted file]
tests/compile-fail/transmute-pair-undef.rs [deleted file]
tests/compiletest.rs

index 04a263597c0b23c41b307bfd7e5d12ca4aab7ad9..5eb7b34425e6e9641b4da080e4b80156926283f8 100644 (file)
--- a/README.md
+++ b/README.md
@@ -45,14 +45,19 @@ in this directory.
 ## Running Miri
 
 ```sh
-cargo +nightly run tests/run-pass/vecs.rs # Or whatever test you like.
+cargo +nightly run -- -Zmiri-disable-validation tests/run-pass/vecs.rs # Or whatever test you like.
 ```
 
+We have to disable validation because that can lead to errors when libstd is not
+compiled the right way.
+
 ## Running Miri with full libstd
 
-Per default libstd does not contain the MIR of non-polymorphic functions. When
-Miri hits a call to such a function, execution terminates. To fix this, it is
-possible to compile libstd with full MIR:
+Per default libstd does not contain the MIR of non-polymorphic functions, and
+also does not contain some extra MIR statements that miri needs for validation.
+When Miri hits a call to such a function, execution terminates, and even when
+the MIR is present, validation can fail.  To fix this, it is possible to compile
+libstd with full MIR:
 
 ```sh
 rustup component add --toolchain nightly rust-src
diff --git a/tests/compile-fail-fullmir/copy_nonoverlapping.rs b/tests/compile-fail-fullmir/copy_nonoverlapping.rs
new file mode 100644 (file)
index 0000000..8e8912c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(core_intrinsics)]
+
+//error-pattern: copy_nonoverlapping called on overlapping ranges
+
+fn main() {
+    let mut data = [0u8; 16];
+    unsafe {
+        let a = data.as_mut_ptr();
+        let b = a.wrapping_offset(1) as *mut _;
+        std::ptr::copy_nonoverlapping(a, b, 2);
+    }
+}
diff --git a/tests/compile-fail-fullmir/memleak_rc.rs b/tests/compile-fail-fullmir/memleak_rc.rs
new file mode 100644 (file)
index 0000000..14a85ec
--- /dev/null
@@ -0,0 +1,15 @@
+// ignore-windows: We do not check leaks on Windows
+// ignore-macos: We do not check leaks on macOS
+
+//error-pattern: the evaluated program leaked memory
+
+use std::rc::Rc;
+use std::cell::RefCell;
+
+struct Dummy(Rc<RefCell<Option<Dummy>>>);
+
+fn main() {
+    let x = Dummy(Rc::new(RefCell::new(None)));
+    let y = Dummy(x.0.clone());
+    *x.0.borrow_mut() = Some(y);
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/alias_through_mutation.rs b/tests/compile-fail-fullmir/stacked_borrows/alias_through_mutation.rs
new file mode 100644 (file)
index 0000000..092f3f0
--- /dev/null
@@ -0,0 +1,15 @@
+#![allow(unused_variables)]
+
+// This makes a ref that was passed to us via &mut alias with things it should not alias with
+fn retarget(x: &mut &u32, target: &mut u32) {
+    unsafe { *x = &mut *(target as *mut _); }
+}
+
+fn main() {
+    let target = &mut 42;
+    let mut target_alias = &42; // initial dummy value
+    retarget(&mut target_alias, target);
+    // now `target_alias` points to the same thing as `target`
+    *target = 13;
+    let _val = *target_alias; //~ ERROR does not exist on the stack
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut1.rs b/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut1.rs
new file mode 100644 (file)
index 0000000..e812e13
--- /dev/null
@@ -0,0 +1,12 @@
+// ignore-test validation_op is disabled
+
+#![allow(unused_variables)]
+
+mod safe {
+    pub fn safe(x: &mut i32, y: &mut i32) {} //~ ERROR: in conflict with lock WriteLock
+}
+
+fn main() {
+    let x = &mut 0 as *mut _;
+    unsafe { safe::safe(&mut *x, &mut *x) };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut2.rs b/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut2.rs
new file mode 100644 (file)
index 0000000..36ebcc2
--- /dev/null
@@ -0,0 +1,12 @@
+// ignore-test validation_op is disabled
+
+#![allow(unused_variables)]
+
+mod safe {
+    pub fn safe(x: &i32, y: &mut i32) {} //~ ERROR: in conflict with lock ReadLock
+}
+
+fn main() {
+    let x = &mut 0 as *mut _;
+    unsafe { safe::safe(&*x, &mut *x) };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut3.rs b/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut3.rs
new file mode 100644 (file)
index 0000000..ad50fbd
--- /dev/null
@@ -0,0 +1,12 @@
+// ignore-test validation_op is disabled
+
+#![allow(unused_variables)]
+
+mod safe {
+    pub fn safe(x: &mut i32, y: &i32) {} //~ ERROR: in conflict with lock WriteLock
+}
+
+fn main() {
+    let x = &mut 0 as *mut _;
+    unsafe { safe::safe(&mut *x, &*x) };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut4.rs b/tests/compile-fail-fullmir/stacked_borrows/aliasing_mut4.rs
new file mode 100644 (file)
index 0000000..a0f0a3c
--- /dev/null
@@ -0,0 +1,15 @@
+// ignore-test validation_op is disabled
+
+#![allow(unused_variables)]
+
+mod safe {
+    use std::cell::Cell;
+
+    // Make sure &mut UnsafeCell also has a lock to it
+    pub fn safe(x: &mut Cell<i32>, y: &i32) {} //~ ERROR: in conflict with lock WriteLock
+}
+
+fn main() {
+    let x = &mut 0 as *mut _;
+    unsafe { safe::safe(&mut *(x as *mut _), &*x) };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/buggy_as_mut_slice.rs b/tests/compile-fail-fullmir/stacked_borrows/buggy_as_mut_slice.rs
new file mode 100644 (file)
index 0000000..2f3d079
--- /dev/null
@@ -0,0 +1,21 @@
+// error-pattern: mutable reference with frozen tag
+
+mod safe {
+    use std::slice::from_raw_parts_mut;
+
+    pub fn as_mut_slice<T>(self_: &Vec<T>) -> &mut [T] {
+        unsafe {
+            from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len())
+        }
+    }
+}
+
+fn main() {
+    let v = vec![0,1,2];
+    let _v1 = safe::as_mut_slice(&v);
+/*
+    let v2 = safe::as_mut_slice(&v);
+    v1[1] = 5;
+    v1[1] = 6;
+*/
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/buggy_split_at_mut.rs b/tests/compile-fail-fullmir/stacked_borrows/buggy_split_at_mut.rs
new file mode 100644 (file)
index 0000000..711544f
--- /dev/null
@@ -0,0 +1,25 @@
+#![allow(unused_variables)]
+
+mod safe {
+    use std::slice::from_raw_parts_mut;
+
+    pub fn split_at_mut<T>(self_: &mut [T], mid: usize) -> (&mut [T], &mut [T]) {
+        let len = self_.len();
+        let ptr = self_.as_mut_ptr();
+
+        unsafe {
+            assert!(mid <= len);
+
+            (from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid"
+            from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+        }
+    }
+}
+
+fn main() {
+    let mut array = [1,2,3,4];
+    let (a, b) = safe::split_at_mut(&mut array, 0);
+    //~^ ERROR does not exist on the stack
+    a[1] = 5;
+    b[1] = 6;
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_read1.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_read1.rs
new file mode 100644 (file)
index 0000000..dbaccae
--- /dev/null
@@ -0,0 +1,15 @@
+// A callee may not read the destination of our `&mut` without
+// us noticing.
+
+fn main() {
+    let mut x = 15;
+    let xraw = &mut x as *mut _;
+    let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
+    callee(xraw);
+    let _val = *xref; // ...but any use of raw will invalidate our ref.
+    //~^ ERROR: does not exist on the stack
+}
+
+fn callee(xraw: *mut i32) {
+    let _val = unsafe { *xraw };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_read2.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_read2.rs
new file mode 100644 (file)
index 0000000..2da755d
--- /dev/null
@@ -0,0 +1,18 @@
+// A callee may not read the destination of our `&mut` without
+// us noticing.
+
+fn main() {
+    let mut x = 15;
+    let xraw = &mut x as *mut _;
+    let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
+    callee(xraw);
+    let _val = *xref; // ...but any use of raw will invalidate our ref.
+    //~^ ERROR: does not exist on the stack
+}
+
+fn callee(xraw: *mut i32) {
+    // We are a bit sneaky: We first create a shared ref, exploiting the reborrowing rules,
+    // and then we read through that.
+    let shr = unsafe { &*xraw };
+    let _val = *shr;
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_read3.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_read3.rs
new file mode 100644 (file)
index 0000000..b0da051
--- /dev/null
@@ -0,0 +1,29 @@
+#![feature(untagged_unions)]
+// A callee may not read the destination of our `&mut` without
+// us noticing.
+// Thise code got carefully checked to not introduce any reborrows
+// that are not explicit in the source.  Let's hope the compiler does not break this later!
+
+use std::mem;
+
+fn main() {
+    let mut x: i32 = 15;
+    let xref1 = &mut x;
+    let xref1_sneaky: usize = unsafe { mem::transmute_copy(&xref1) };
+    let xref2 = &mut *xref1; // derived from xref1, so using raw is still okay...
+    callee(xref1_sneaky);
+    let _val = *xref2; // ...but any use of it will invalidate our ref.
+    //~^ ERROR: does not exist on the stack
+}
+
+fn callee(xref1: usize) {
+    // Transmuting through a union to avoid retagging
+    union UsizeToRef {
+        from: usize,
+        to: &'static mut i32,
+    }
+    let xref1 = UsizeToRef { from: xref1 };
+    // Doing the deref and the transmute (through the union) in the same place expression
+    // should avoid retagging.
+    let _val = unsafe { *xref1.to };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_read4.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_read4.rs
new file mode 100644 (file)
index 0000000..c86ec12
--- /dev/null
@@ -0,0 +1,9 @@
+// Using a raw invalidates derived `&mut` even for reading.
+fn main() {
+    let mut x = 2;
+    let xref1 = &mut x;
+    let xraw = xref1 as *mut _;
+    let xref2 = unsafe { &mut *xraw };
+    let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs
+    let _illegal = *xref2; //~ ERROR does not exist on the stack
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_read5.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_read5.rs
new file mode 100644 (file)
index 0000000..863649a
--- /dev/null
@@ -0,0 +1,16 @@
+// We *can* have aliasing &RefCell<T> and &mut T, but we cannot read through the former.
+// Else we couldn't optimize based on the assumption that `xref` below is truly unique.
+
+use std::cell::RefCell;
+use std::{mem, ptr};
+
+fn main() {
+    let rc = RefCell::new(0);
+    let mut refmut = rc.borrow_mut();
+    let xref: &mut i32 = &mut *refmut;
+    let xshr = &rc; // creating this is okay
+    let _val = *xref; // we can even still use our mutable reference
+    mem::forget(unsafe { ptr::read(xshr) }); // but after reading through the shared ref
+    let _val = *xref; // the mutable one is dead and gone
+    //~^ ERROR does not exist on the stack
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_write1.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_write1.rs
new file mode 100644 (file)
index 0000000..b106cc8
--- /dev/null
@@ -0,0 +1,12 @@
+fn evil(x: &u32) {
+    // mutating shared ref without `UnsafeCell`
+    let x : *mut u32 = x as *const _ as *mut _;
+    unsafe { *x = 42; }
+}
+
+fn main() {
+    let target = Box::new(42); // has an implicit raw
+    let ref_ = &*target;
+    evil(ref_); // invalidates shared ref, activates raw
+    let _x = *ref_; //~ ERROR is not frozen
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_write2.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_write2.rs
new file mode 100644 (file)
index 0000000..b53655c
--- /dev/null
@@ -0,0 +1,14 @@
+// We fail to detect this when neither this nor libstd are optimized/have retagging.
+// FIXME: Investigate that.
+// compile-flags: -Zmir-opt-level=0
+
+#![allow(unused_variables)]
+
+fn main() {
+    let target = &mut 42;
+    let target2 = target as *mut _;
+    drop(&mut *target); // reborrow
+    // Now make sure our ref is still the only one.
+    unsafe { *target2 = 13; } //~ ERROR does not exist on the stack
+    let _val = *target;
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_write3.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_write3.rs
new file mode 100644 (file)
index 0000000..01559af
--- /dev/null
@@ -0,0 +1,8 @@
+fn main() {
+    let target = 42;
+    // Make sure raw ptr with raw tag cannot mutate frozen location without breaking the shared ref.
+    let r#ref = &target; // freeze
+    let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag
+    unsafe { *ptr = 42; }
+    let _val = *r#ref; //~ ERROR is not frozen
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_write4.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_write4.rs
new file mode 100644 (file)
index 0000000..37ae0f0
--- /dev/null
@@ -0,0 +1,13 @@
+use std::mem;
+
+fn main() {
+    let mut target = 42;
+    // Make sure we cannot use a raw-tagged `&mut` pointing to a frozen location.
+    // Even just creating it unfreezes.
+    let raw = &mut target as *mut _; // let this leak to raw
+    let reference = unsafe { &*raw }; // freeze
+    let ptr = reference as *const _ as *mut i32; // raw ptr, with raw tag
+    let _mut_ref: &mut i32 = unsafe { mem::transmute(ptr) }; // &mut, with raw tag
+    // Now we retag, making our ref top-of-stack -- and, in particular, unfreezing.
+    let _val = *reference; //~ ERROR is not frozen
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/illegal_write5.rs b/tests/compile-fail-fullmir/stacked_borrows/illegal_write5.rs
new file mode 100644 (file)
index 0000000..57b2ca8
--- /dev/null
@@ -0,0 +1,15 @@
+// A callee may not write to the destination of our `&mut` without
+// us noticing.
+
+fn main() {
+    let mut x = 15;
+    let xraw = &mut x as *mut _;
+    let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
+    callee(xraw);
+    let _val = *xref; // ...but any use of raw will invalidate our ref.
+    //~^ ERROR: does not exist on the stack
+}
+
+fn callee(xraw: *mut i32) {
+    unsafe { *xraw = 15 };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/load_invalid_mut.rs b/tests/compile-fail-fullmir/stacked_borrows/load_invalid_mut.rs
new file mode 100644 (file)
index 0000000..98b9451
--- /dev/null
@@ -0,0 +1,9 @@
+// Make sure that we cannot load from memory a `&mut` that got already invalidated.
+fn main() {
+    let x = &mut 42;
+    let xraw = x as *mut _;
+    let xref = unsafe { &mut *xraw };
+    let xref_in_mem = Box::new(xref);
+    let _val = unsafe { *xraw }; // invalidate xref
+    let _val = *xref_in_mem; //~ ERROR does not exist on the stack
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/load_invalid_shr.rs b/tests/compile-fail-fullmir/stacked_borrows/load_invalid_shr.rs
new file mode 100644 (file)
index 0000000..6599924
--- /dev/null
@@ -0,0 +1,9 @@
+// Make sure that we cannot load from memory a `&` that got already invalidated.
+fn main() {
+    let x = &mut 42;
+    let xraw = x as *mut _;
+    let xref = unsafe { &*xraw };
+    let xref_in_mem = Box::new(xref);
+    unsafe { *xraw = 42 }; // unfreeze
+    let _val = *xref_in_mem; //~ ERROR is not frozen
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/mut_exclusive_violation1.rs b/tests/compile-fail-fullmir/stacked_borrows/mut_exclusive_violation1.rs
new file mode 100644 (file)
index 0000000..255e35b
--- /dev/null
@@ -0,0 +1,29 @@
+fn demo_mut_advanced_unique(our: &mut i32) -> i32 {
+  unknown_code_1(&*our);
+
+  // This "re-asserts" uniqueness of the reference: After writing, we know
+  // our tag is at the top of the stack.
+  *our = 5;
+
+  unknown_code_2();
+
+  // We know this will return 5
+  *our
+}
+
+// Now comes the evil context
+use std::ptr;
+
+static mut LEAK: *mut i32 = ptr::null_mut();
+
+fn unknown_code_1(x: &i32) { unsafe {
+    LEAK = x as *const _ as *mut _;
+} }
+
+fn unknown_code_2() { unsafe {
+    *LEAK = 7; //~ ERROR does not exist on the stack
+} }
+
+fn main() {
+    assert_eq!(demo_mut_advanced_unique(&mut 0), 5);
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/outdated_local.rs b/tests/compile-fail-fullmir/stacked_borrows/outdated_local.rs
new file mode 100644 (file)
index 0000000..64a8ff6
--- /dev/null
@@ -0,0 +1,9 @@
+fn main() {
+    let mut x = 0;
+    let y: *const i32 = &x;
+    x = 1; // this invalidates y by reactivating the lowermost uniq borrow for this local
+
+    assert_eq!(unsafe { *y }, 1); //~ ERROR does not exist on the stack
+
+    assert_eq!(x, 1);
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/pass_invalid_mut.rs b/tests/compile-fail-fullmir/stacked_borrows/pass_invalid_mut.rs
new file mode 100644 (file)
index 0000000..28288c6
--- /dev/null
@@ -0,0 +1,10 @@
+// Make sure that we cannot pass by argument a `&mut` that got already invalidated.
+fn foo(_: &mut i32) {}
+
+fn main() {
+    let x = &mut 42;
+    let xraw = x as *mut _;
+    let xref = unsafe { &mut *xraw };
+    let _val = unsafe { *xraw }; // invalidate xref
+    foo(xref); //~ ERROR does not exist on the stack
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/pass_invalid_shr.rs b/tests/compile-fail-fullmir/stacked_borrows/pass_invalid_shr.rs
new file mode 100644 (file)
index 0000000..67bbc88
--- /dev/null
@@ -0,0 +1,10 @@
+// Make sure that we cannot pass by argument a `&` that got already invalidated.
+fn foo(_: &i32) {}
+
+fn main() {
+    let x = &mut 42;
+    let xraw = &*x as *const _ as *mut _;
+    let xref = unsafe { &*xraw };
+    unsafe { *xraw = 42 }; // unfreeze
+    foo(xref); //~ ERROR is not frozen
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/pointer_smuggling.rs b/tests/compile-fail-fullmir/stacked_borrows/pointer_smuggling.rs
new file mode 100644 (file)
index 0000000..68f3d29
--- /dev/null
@@ -0,0 +1,21 @@
+#![allow(unused_variables)]
+
+static mut PTR: *mut u8 = 0 as *mut _;
+
+fn fun1(x: &mut u8) {
+    unsafe {
+        PTR = x;
+    }
+}
+
+fn fun2() {
+    // Now we use a pointer we are not allowed to use
+    let _x = unsafe { *PTR }; //~ ERROR does not exist on the stack
+}
+
+fn main() {
+    let val = &mut 0; // FIXME: This should also work with a local variable, but currently it does not.
+    fun1(val);
+    *val = 2; // this invalidates any raw ptrs `fun1` might have created.
+    fun2(); // if they now use a raw ptr they break our reference
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/return_invalid_mut.rs b/tests/compile-fail-fullmir/stacked_borrows/return_invalid_mut.rs
new file mode 100644 (file)
index 0000000..e7f0b9b
--- /dev/null
@@ -0,0 +1,11 @@
+// Make sure that we cannot return a `&mut` that got already invalidated.
+fn foo(x: &mut (i32, i32)) -> &mut i32 {
+    let xraw = x as *mut (i32, i32);
+    let ret = unsafe { &mut (*xraw).1 };
+    let _val = unsafe { *xraw }; // invalidate xref
+    ret //~ ERROR does not exist on the stack
+}
+
+fn main() {
+    foo(&mut (1, 2));
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/return_invalid_shr.rs b/tests/compile-fail-fullmir/stacked_borrows/return_invalid_shr.rs
new file mode 100644 (file)
index 0000000..986dd18
--- /dev/null
@@ -0,0 +1,11 @@
+// Make sure that we cannot return a `&` that got already invalidated.
+fn foo(x: &mut (i32, i32)) -> &i32 {
+    let xraw = x as *mut (i32, i32);
+    let ret = unsafe { &(*xraw).1 };
+    unsafe { *xraw = (42, 23) }; // unfreeze
+    ret //~ ERROR is not frozen
+}
+
+fn main() {
+    foo(&mut (1, 2));
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/static_memory_modification.rs b/tests/compile-fail-fullmir/stacked_borrows/static_memory_modification.rs
new file mode 100644 (file)
index 0000000..5c605ef
--- /dev/null
@@ -0,0 +1,11 @@
+// FIXME still considering whether we are okay with this not being an error
+// ignore-test
+
+static X: usize = 5;
+
+#[allow(mutable_transmutes)]
+fn main() {
+    let _x = unsafe {
+        std::mem::transmute::<&usize, &mut usize>(&X) //~ ERROR mutable reference with frozen tag
+    };
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/transmute-is-no-escape.rs b/tests/compile-fail-fullmir/stacked_borrows/transmute-is-no-escape.rs
new file mode 100644 (file)
index 0000000..1ab005e
--- /dev/null
@@ -0,0 +1,12 @@
+// Make sure we cannot use raw ptrs that got transmuted from mutable references
+// (i.e, no EscapeToRaw happened).
+// We could, in principle, to EscapeToRaw lazily to allow this code, but that
+// would no alleviate the need for EscapeToRaw (see `ref_raw_int_raw` in
+// `run-pass/stacked-borrows.rs`), and thus increase overall complexity.
+use std::mem;
+
+fn main() {
+    let mut x: i32 = 42;
+    let raw: *mut i32 = unsafe { mem::transmute(&mut x) };
+    unsafe { *raw = 13; } //~ ERROR does not exist on the stack
+}
diff --git a/tests/compile-fail-fullmir/stacked_borrows/unescaped_local.rs b/tests/compile-fail-fullmir/stacked_borrows/unescaped_local.rs
new file mode 100644 (file)
index 0000000..054697b
--- /dev/null
@@ -0,0 +1,8 @@
+// Make sure we cannot use raw ptrs to access a local that
+// we took the direct address of.
+fn main() {
+    let mut x = 42;
+    let raw = &mut x as *mut i32 as usize as *mut i32;
+    let _ptr = &mut x;
+    unsafe { *raw = 13; } //~ ERROR does not exist on the stack
+}
diff --git a/tests/compile-fail-fullmir/transmute-pair-undef.rs b/tests/compile-fail-fullmir/transmute-pair-undef.rs
new file mode 100644 (file)
index 0000000..acc6098
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(core_intrinsics)]
+
+use std::mem;
+
+fn main() {
+    let x: Option<Box<[u8]>> = unsafe {
+        let z = std::intrinsics::add_with_overflow(0usize, 0usize);
+        std::mem::transmute::<(usize, bool), Option<Box<[u8]>>>(z)
+    };
+    let y = &x;
+    // Now read this bytewise.  There should be (ptr_size+1) def bytes followed by (ptr_size-1) undef bytes (the padding after the bool) in there.
+    let z : *const u8 = y as *const _ as *const _;
+    let first_undef = mem::size_of::<usize>() as isize + 1;
+    for i in 0..first_undef {
+        let byte = unsafe { *z.offset(i) };
+        assert_eq!(byte, 0);
+    }
+    let v = unsafe { *z.offset(first_undef) };
+    if v == 0 {} //~ ERROR attempted to read undefined bytes
+}
diff --git a/tests/compile-fail/copy_nonoverlapping.rs b/tests/compile-fail/copy_nonoverlapping.rs
deleted file mode 100644 (file)
index 8e8912c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(core_intrinsics)]
-
-//error-pattern: copy_nonoverlapping called on overlapping ranges
-
-fn main() {
-    let mut data = [0u8; 16];
-    unsafe {
-        let a = data.as_mut_ptr();
-        let b = a.wrapping_offset(1) as *mut _;
-        std::ptr::copy_nonoverlapping(a, b, 2);
-    }
-}
diff --git a/tests/compile-fail/memleak_rc.rs b/tests/compile-fail/memleak_rc.rs
deleted file mode 100644 (file)
index 14a85ec..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// ignore-windows: We do not check leaks on Windows
-// ignore-macos: We do not check leaks on macOS
-
-//error-pattern: the evaluated program leaked memory
-
-use std::rc::Rc;
-use std::cell::RefCell;
-
-struct Dummy(Rc<RefCell<Option<Dummy>>>);
-
-fn main() {
-    let x = Dummy(Rc::new(RefCell::new(None)));
-    let y = Dummy(x.0.clone());
-    *x.0.borrow_mut() = Some(y);
-}
diff --git a/tests/compile-fail/stacked_borrows/alias_through_mutation.rs b/tests/compile-fail/stacked_borrows/alias_through_mutation.rs
deleted file mode 100644 (file)
index 092f3f0..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#![allow(unused_variables)]
-
-// This makes a ref that was passed to us via &mut alias with things it should not alias with
-fn retarget(x: &mut &u32, target: &mut u32) {
-    unsafe { *x = &mut *(target as *mut _); }
-}
-
-fn main() {
-    let target = &mut 42;
-    let mut target_alias = &42; // initial dummy value
-    retarget(&mut target_alias, target);
-    // now `target_alias` points to the same thing as `target`
-    *target = 13;
-    let _val = *target_alias; //~ ERROR does not exist on the stack
-}
diff --git a/tests/compile-fail/stacked_borrows/aliasing_mut1.rs b/tests/compile-fail/stacked_borrows/aliasing_mut1.rs
deleted file mode 100644 (file)
index e812e13..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// ignore-test validation_op is disabled
-
-#![allow(unused_variables)]
-
-mod safe {
-    pub fn safe(x: &mut i32, y: &mut i32) {} //~ ERROR: in conflict with lock WriteLock
-}
-
-fn main() {
-    let x = &mut 0 as *mut _;
-    unsafe { safe::safe(&mut *x, &mut *x) };
-}
diff --git a/tests/compile-fail/stacked_borrows/aliasing_mut2.rs b/tests/compile-fail/stacked_borrows/aliasing_mut2.rs
deleted file mode 100644 (file)
index 36ebcc2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// ignore-test validation_op is disabled
-
-#![allow(unused_variables)]
-
-mod safe {
-    pub fn safe(x: &i32, y: &mut i32) {} //~ ERROR: in conflict with lock ReadLock
-}
-
-fn main() {
-    let x = &mut 0 as *mut _;
-    unsafe { safe::safe(&*x, &mut *x) };
-}
diff --git a/tests/compile-fail/stacked_borrows/aliasing_mut3.rs b/tests/compile-fail/stacked_borrows/aliasing_mut3.rs
deleted file mode 100644 (file)
index ad50fbd..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// ignore-test validation_op is disabled
-
-#![allow(unused_variables)]
-
-mod safe {
-    pub fn safe(x: &mut i32, y: &i32) {} //~ ERROR: in conflict with lock WriteLock
-}
-
-fn main() {
-    let x = &mut 0 as *mut _;
-    unsafe { safe::safe(&mut *x, &*x) };
-}
diff --git a/tests/compile-fail/stacked_borrows/aliasing_mut4.rs b/tests/compile-fail/stacked_borrows/aliasing_mut4.rs
deleted file mode 100644 (file)
index a0f0a3c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// ignore-test validation_op is disabled
-
-#![allow(unused_variables)]
-
-mod safe {
-    use std::cell::Cell;
-
-    // Make sure &mut UnsafeCell also has a lock to it
-    pub fn safe(x: &mut Cell<i32>, y: &i32) {} //~ ERROR: in conflict with lock WriteLock
-}
-
-fn main() {
-    let x = &mut 0 as *mut _;
-    unsafe { safe::safe(&mut *(x as *mut _), &*x) };
-}
diff --git a/tests/compile-fail/stacked_borrows/buggy_as_mut_slice.rs b/tests/compile-fail/stacked_borrows/buggy_as_mut_slice.rs
deleted file mode 100644 (file)
index 2f3d079..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// error-pattern: mutable reference with frozen tag
-
-mod safe {
-    use std::slice::from_raw_parts_mut;
-
-    pub fn as_mut_slice<T>(self_: &Vec<T>) -> &mut [T] {
-        unsafe {
-            from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len())
-        }
-    }
-}
-
-fn main() {
-    let v = vec![0,1,2];
-    let _v1 = safe::as_mut_slice(&v);
-/*
-    let v2 = safe::as_mut_slice(&v);
-    v1[1] = 5;
-    v1[1] = 6;
-*/
-}
diff --git a/tests/compile-fail/stacked_borrows/buggy_split_at_mut.rs b/tests/compile-fail/stacked_borrows/buggy_split_at_mut.rs
deleted file mode 100644 (file)
index 711544f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#![allow(unused_variables)]
-
-mod safe {
-    use std::slice::from_raw_parts_mut;
-
-    pub fn split_at_mut<T>(self_: &mut [T], mid: usize) -> (&mut [T], &mut [T]) {
-        let len = self_.len();
-        let ptr = self_.as_mut_ptr();
-
-        unsafe {
-            assert!(mid <= len);
-
-            (from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid"
-            from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
-        }
-    }
-}
-
-fn main() {
-    let mut array = [1,2,3,4];
-    let (a, b) = safe::split_at_mut(&mut array, 0);
-    //~^ ERROR does not exist on the stack
-    a[1] = 5;
-    b[1] = 6;
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_read1.rs b/tests/compile-fail/stacked_borrows/illegal_read1.rs
deleted file mode 100644 (file)
index dbaccae..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// A callee may not read the destination of our `&mut` without
-// us noticing.
-
-fn main() {
-    let mut x = 15;
-    let xraw = &mut x as *mut _;
-    let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
-    callee(xraw);
-    let _val = *xref; // ...but any use of raw will invalidate our ref.
-    //~^ ERROR: does not exist on the stack
-}
-
-fn callee(xraw: *mut i32) {
-    let _val = unsafe { *xraw };
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_read2.rs b/tests/compile-fail/stacked_borrows/illegal_read2.rs
deleted file mode 100644 (file)
index 2da755d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// A callee may not read the destination of our `&mut` without
-// us noticing.
-
-fn main() {
-    let mut x = 15;
-    let xraw = &mut x as *mut _;
-    let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
-    callee(xraw);
-    let _val = *xref; // ...but any use of raw will invalidate our ref.
-    //~^ ERROR: does not exist on the stack
-}
-
-fn callee(xraw: *mut i32) {
-    // We are a bit sneaky: We first create a shared ref, exploiting the reborrowing rules,
-    // and then we read through that.
-    let shr = unsafe { &*xraw };
-    let _val = *shr;
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_read3.rs b/tests/compile-fail/stacked_borrows/illegal_read3.rs
deleted file mode 100644 (file)
index b0da051..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#![feature(untagged_unions)]
-// A callee may not read the destination of our `&mut` without
-// us noticing.
-// Thise code got carefully checked to not introduce any reborrows
-// that are not explicit in the source.  Let's hope the compiler does not break this later!
-
-use std::mem;
-
-fn main() {
-    let mut x: i32 = 15;
-    let xref1 = &mut x;
-    let xref1_sneaky: usize = unsafe { mem::transmute_copy(&xref1) };
-    let xref2 = &mut *xref1; // derived from xref1, so using raw is still okay...
-    callee(xref1_sneaky);
-    let _val = *xref2; // ...but any use of it will invalidate our ref.
-    //~^ ERROR: does not exist on the stack
-}
-
-fn callee(xref1: usize) {
-    // Transmuting through a union to avoid retagging
-    union UsizeToRef {
-        from: usize,
-        to: &'static mut i32,
-    }
-    let xref1 = UsizeToRef { from: xref1 };
-    // Doing the deref and the transmute (through the union) in the same place expression
-    // should avoid retagging.
-    let _val = unsafe { *xref1.to };
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_read4.rs b/tests/compile-fail/stacked_borrows/illegal_read4.rs
deleted file mode 100644 (file)
index c86ec12..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// Using a raw invalidates derived `&mut` even for reading.
-fn main() {
-    let mut x = 2;
-    let xref1 = &mut x;
-    let xraw = xref1 as *mut _;
-    let xref2 = unsafe { &mut *xraw };
-    let _val = unsafe { *xraw }; // use the raw again, this invalidates xref2 *even* with the special read except for uniq refs
-    let _illegal = *xref2; //~ ERROR does not exist on the stack
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_read5.rs b/tests/compile-fail/stacked_borrows/illegal_read5.rs
deleted file mode 100644 (file)
index 863649a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// We *can* have aliasing &RefCell<T> and &mut T, but we cannot read through the former.
-// Else we couldn't optimize based on the assumption that `xref` below is truly unique.
-
-use std::cell::RefCell;
-use std::{mem, ptr};
-
-fn main() {
-    let rc = RefCell::new(0);
-    let mut refmut = rc.borrow_mut();
-    let xref: &mut i32 = &mut *refmut;
-    let xshr = &rc; // creating this is okay
-    let _val = *xref; // we can even still use our mutable reference
-    mem::forget(unsafe { ptr::read(xshr) }); // but after reading through the shared ref
-    let _val = *xref; // the mutable one is dead and gone
-    //~^ ERROR does not exist on the stack
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_write1.rs b/tests/compile-fail/stacked_borrows/illegal_write1.rs
deleted file mode 100644 (file)
index b106cc8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-fn evil(x: &u32) {
-    // mutating shared ref without `UnsafeCell`
-    let x : *mut u32 = x as *const _ as *mut _;
-    unsafe { *x = 42; }
-}
-
-fn main() {
-    let target = Box::new(42); // has an implicit raw
-    let ref_ = &*target;
-    evil(ref_); // invalidates shared ref, activates raw
-    let _x = *ref_; //~ ERROR is not frozen
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_write2.rs b/tests/compile-fail/stacked_borrows/illegal_write2.rs
deleted file mode 100644 (file)
index b53655c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// We fail to detect this when neither this nor libstd are optimized/have retagging.
-// FIXME: Investigate that.
-// compile-flags: -Zmir-opt-level=0
-
-#![allow(unused_variables)]
-
-fn main() {
-    let target = &mut 42;
-    let target2 = target as *mut _;
-    drop(&mut *target); // reborrow
-    // Now make sure our ref is still the only one.
-    unsafe { *target2 = 13; } //~ ERROR does not exist on the stack
-    let _val = *target;
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_write3.rs b/tests/compile-fail/stacked_borrows/illegal_write3.rs
deleted file mode 100644 (file)
index 01559af..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-fn main() {
-    let target = 42;
-    // Make sure raw ptr with raw tag cannot mutate frozen location without breaking the shared ref.
-    let r#ref = &target; // freeze
-    let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag
-    unsafe { *ptr = 42; }
-    let _val = *r#ref; //~ ERROR is not frozen
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_write4.rs b/tests/compile-fail/stacked_borrows/illegal_write4.rs
deleted file mode 100644 (file)
index 37ae0f0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-use std::mem;
-
-fn main() {
-    let mut target = 42;
-    // Make sure we cannot use a raw-tagged `&mut` pointing to a frozen location.
-    // Even just creating it unfreezes.
-    let raw = &mut target as *mut _; // let this leak to raw
-    let reference = unsafe { &*raw }; // freeze
-    let ptr = reference as *const _ as *mut i32; // raw ptr, with raw tag
-    let _mut_ref: &mut i32 = unsafe { mem::transmute(ptr) }; // &mut, with raw tag
-    // Now we retag, making our ref top-of-stack -- and, in particular, unfreezing.
-    let _val = *reference; //~ ERROR is not frozen
-}
diff --git a/tests/compile-fail/stacked_borrows/illegal_write5.rs b/tests/compile-fail/stacked_borrows/illegal_write5.rs
deleted file mode 100644 (file)
index 57b2ca8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// A callee may not write to the destination of our `&mut` without
-// us noticing.
-
-fn main() {
-    let mut x = 15;
-    let xraw = &mut x as *mut _;
-    let xref = unsafe { &mut *xraw }; // derived from raw, so using raw is still okay...
-    callee(xraw);
-    let _val = *xref; // ...but any use of raw will invalidate our ref.
-    //~^ ERROR: does not exist on the stack
-}
-
-fn callee(xraw: *mut i32) {
-    unsafe { *xraw = 15 };
-}
diff --git a/tests/compile-fail/stacked_borrows/load_invalid_mut.rs b/tests/compile-fail/stacked_borrows/load_invalid_mut.rs
deleted file mode 100644 (file)
index 98b9451..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// Make sure that we cannot load from memory a `&mut` that got already invalidated.
-fn main() {
-    let x = &mut 42;
-    let xraw = x as *mut _;
-    let xref = unsafe { &mut *xraw };
-    let xref_in_mem = Box::new(xref);
-    let _val = unsafe { *xraw }; // invalidate xref
-    let _val = *xref_in_mem; //~ ERROR does not exist on the stack
-}
diff --git a/tests/compile-fail/stacked_borrows/load_invalid_shr.rs b/tests/compile-fail/stacked_borrows/load_invalid_shr.rs
deleted file mode 100644 (file)
index 6599924..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// Make sure that we cannot load from memory a `&` that got already invalidated.
-fn main() {
-    let x = &mut 42;
-    let xraw = x as *mut _;
-    let xref = unsafe { &*xraw };
-    let xref_in_mem = Box::new(xref);
-    unsafe { *xraw = 42 }; // unfreeze
-    let _val = *xref_in_mem; //~ ERROR is not frozen
-}
diff --git a/tests/compile-fail/stacked_borrows/mut_exclusive_violation1.rs b/tests/compile-fail/stacked_borrows/mut_exclusive_violation1.rs
deleted file mode 100644 (file)
index 255e35b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-fn demo_mut_advanced_unique(our: &mut i32) -> i32 {
-  unknown_code_1(&*our);
-
-  // This "re-asserts" uniqueness of the reference: After writing, we know
-  // our tag is at the top of the stack.
-  *our = 5;
-
-  unknown_code_2();
-
-  // We know this will return 5
-  *our
-}
-
-// Now comes the evil context
-use std::ptr;
-
-static mut LEAK: *mut i32 = ptr::null_mut();
-
-fn unknown_code_1(x: &i32) { unsafe {
-    LEAK = x as *const _ as *mut _;
-} }
-
-fn unknown_code_2() { unsafe {
-    *LEAK = 7; //~ ERROR does not exist on the stack
-} }
-
-fn main() {
-    assert_eq!(demo_mut_advanced_unique(&mut 0), 5);
-}
diff --git a/tests/compile-fail/stacked_borrows/outdated_local.rs b/tests/compile-fail/stacked_borrows/outdated_local.rs
deleted file mode 100644 (file)
index 64a8ff6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-fn main() {
-    let mut x = 0;
-    let y: *const i32 = &x;
-    x = 1; // this invalidates y by reactivating the lowermost uniq borrow for this local
-
-    assert_eq!(unsafe { *y }, 1); //~ ERROR does not exist on the stack
-
-    assert_eq!(x, 1);
-}
diff --git a/tests/compile-fail/stacked_borrows/pass_invalid_mut.rs b/tests/compile-fail/stacked_borrows/pass_invalid_mut.rs
deleted file mode 100644 (file)
index 28288c6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Make sure that we cannot pass by argument a `&mut` that got already invalidated.
-fn foo(_: &mut i32) {}
-
-fn main() {
-    let x = &mut 42;
-    let xraw = x as *mut _;
-    let xref = unsafe { &mut *xraw };
-    let _val = unsafe { *xraw }; // invalidate xref
-    foo(xref); //~ ERROR does not exist on the stack
-}
diff --git a/tests/compile-fail/stacked_borrows/pass_invalid_shr.rs b/tests/compile-fail/stacked_borrows/pass_invalid_shr.rs
deleted file mode 100644 (file)
index 67bbc88..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Make sure that we cannot pass by argument a `&` that got already invalidated.
-fn foo(_: &i32) {}
-
-fn main() {
-    let x = &mut 42;
-    let xraw = &*x as *const _ as *mut _;
-    let xref = unsafe { &*xraw };
-    unsafe { *xraw = 42 }; // unfreeze
-    foo(xref); //~ ERROR is not frozen
-}
diff --git a/tests/compile-fail/stacked_borrows/pointer_smuggling.rs b/tests/compile-fail/stacked_borrows/pointer_smuggling.rs
deleted file mode 100644 (file)
index 68f3d29..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![allow(unused_variables)]
-
-static mut PTR: *mut u8 = 0 as *mut _;
-
-fn fun1(x: &mut u8) {
-    unsafe {
-        PTR = x;
-    }
-}
-
-fn fun2() {
-    // Now we use a pointer we are not allowed to use
-    let _x = unsafe { *PTR }; //~ ERROR does not exist on the stack
-}
-
-fn main() {
-    let val = &mut 0; // FIXME: This should also work with a local variable, but currently it does not.
-    fun1(val);
-    *val = 2; // this invalidates any raw ptrs `fun1` might have created.
-    fun2(); // if they now use a raw ptr they break our reference
-}
diff --git a/tests/compile-fail/stacked_borrows/return_invalid_mut.rs b/tests/compile-fail/stacked_borrows/return_invalid_mut.rs
deleted file mode 100644 (file)
index e7f0b9b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Make sure that we cannot return a `&mut` that got already invalidated.
-fn foo(x: &mut (i32, i32)) -> &mut i32 {
-    let xraw = x as *mut (i32, i32);
-    let ret = unsafe { &mut (*xraw).1 };
-    let _val = unsafe { *xraw }; // invalidate xref
-    ret //~ ERROR does not exist on the stack
-}
-
-fn main() {
-    foo(&mut (1, 2));
-}
diff --git a/tests/compile-fail/stacked_borrows/return_invalid_shr.rs b/tests/compile-fail/stacked_borrows/return_invalid_shr.rs
deleted file mode 100644 (file)
index 986dd18..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Make sure that we cannot return a `&` that got already invalidated.
-fn foo(x: &mut (i32, i32)) -> &i32 {
-    let xraw = x as *mut (i32, i32);
-    let ret = unsafe { &(*xraw).1 };
-    unsafe { *xraw = (42, 23) }; // unfreeze
-    ret //~ ERROR is not frozen
-}
-
-fn main() {
-    foo(&mut (1, 2));
-}
diff --git a/tests/compile-fail/stacked_borrows/static_memory_modification.rs b/tests/compile-fail/stacked_borrows/static_memory_modification.rs
deleted file mode 100644 (file)
index 5c605ef..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// FIXME still considering whether we are okay with this not being an error
-// ignore-test
-
-static X: usize = 5;
-
-#[allow(mutable_transmutes)]
-fn main() {
-    let _x = unsafe {
-        std::mem::transmute::<&usize, &mut usize>(&X) //~ ERROR mutable reference with frozen tag
-    };
-}
diff --git a/tests/compile-fail/stacked_borrows/transmute-is-no-escape.rs b/tests/compile-fail/stacked_borrows/transmute-is-no-escape.rs
deleted file mode 100644 (file)
index 1ab005e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// Make sure we cannot use raw ptrs that got transmuted from mutable references
-// (i.e, no EscapeToRaw happened).
-// We could, in principle, to EscapeToRaw lazily to allow this code, but that
-// would no alleviate the need for EscapeToRaw (see `ref_raw_int_raw` in
-// `run-pass/stacked-borrows.rs`), and thus increase overall complexity.
-use std::mem;
-
-fn main() {
-    let mut x: i32 = 42;
-    let raw: *mut i32 = unsafe { mem::transmute(&mut x) };
-    unsafe { *raw = 13; } //~ ERROR does not exist on the stack
-}
diff --git a/tests/compile-fail/stacked_borrows/unescaped_local.rs b/tests/compile-fail/stacked_borrows/unescaped_local.rs
deleted file mode 100644 (file)
index 054697b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// Make sure we cannot use raw ptrs to access a local that
-// we took the direct address of.
-fn main() {
-    let mut x = 42;
-    let raw = &mut x as *mut i32 as usize as *mut i32;
-    let _ptr = &mut x;
-    unsafe { *raw = 13; } //~ ERROR does not exist on the stack
-}
diff --git a/tests/compile-fail/transmute-pair-undef.rs b/tests/compile-fail/transmute-pair-undef.rs
deleted file mode 100644 (file)
index acc6098..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#![feature(core_intrinsics)]
-
-use std::mem;
-
-fn main() {
-    let x: Option<Box<[u8]>> = unsafe {
-        let z = std::intrinsics::add_with_overflow(0usize, 0usize);
-        std::mem::transmute::<(usize, bool), Option<Box<[u8]>>>(z)
-    };
-    let y = &x;
-    // Now read this bytewise.  There should be (ptr_size+1) def bytes followed by (ptr_size-1) undef bytes (the padding after the bool) in there.
-    let z : *const u8 = y as *const _ as *const _;
-    let first_undef = mem::size_of::<usize>() as isize + 1;
-    for i in 0..first_undef {
-        let byte = unsafe { *z.offset(i) };
-        assert_eq!(byte, 0);
-    }
-    let v = unsafe { *z.offset(first_undef) };
-    if v == 0 {} //~ ERROR attempted to read undefined bytes
-}
index f393fcb2c226fd2daeac2212419f8ce1b50f395c..7ecf64590b6148fd2af5e57f0bb89ceb76a96c7e 100644 (file)
@@ -103,6 +103,10 @@ fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, need_fullmir:
         // whitelist.
         flags.push("-Zmir-opt-level=1".to_owned());
     }
+    if !have_fullmir() {
+        // Validation relies on the EscapeToRaw statements being emitted
+        flags.push("-Zmiri-disable-validation".to_owned());
+    }
 
     let mut config = mk_config("ui");
     config.src_base = PathBuf::from(path);