Skip to content

Commit dd94930

Browse files
committed
implement function barriers
1 parent 215ec38 commit dd94930

10 files changed

+174
-94
lines changed

src/stacked_borrows.rs

Lines changed: 90 additions & 52 deletions
Large diffs are not rendered by default.
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
// ignore-test validation_op is disabled
2-
31
#![allow(unused_variables)]
42

5-
mod safe {
6-
pub fn safe(x: &mut i32, y: &mut i32) {} //~ ERROR: in conflict with lock WriteLock
7-
}
3+
use std::mem;
4+
5+
pub fn safe(x: &mut i32, y: &mut i32) {} //~ ERROR barrier
86

97
fn main() {
10-
let x = &mut 0 as *mut _;
11-
unsafe { safe::safe(&mut *x, &mut *x) };
8+
let mut x = 0;
9+
let xraw: *mut i32 = unsafe { mem::transmute(&mut x) };
10+
// We need to apply some tricky to be able to call `safe` with two mutable references
11+
// with the same tag: We transmute both the fn ptr (to take raw ptrs) and the argument
12+
// (to be raw, but still have the unique tag).
13+
let safe_raw: fn(x: *mut i32, y: *mut i32) = unsafe {
14+
mem::transmute::<fn(&mut i32, &mut i32), _>(safe)
15+
};
16+
safe_raw(xraw, xraw);
1217
}
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
// ignore-test validation_op is disabled
2-
31
#![allow(unused_variables)]
42

5-
mod safe {
6-
pub fn safe(x: &i32, y: &mut i32) {} //~ ERROR: in conflict with lock ReadLock
7-
}
3+
use std::mem;
4+
5+
pub fn safe(x: &i32, y: &mut i32) {} //~ ERROR barrier
86

97
fn main() {
10-
let x = &mut 0 as *mut _;
11-
unsafe { safe::safe(&*x, &mut *x) };
8+
let mut x = 0;
9+
let xref = &mut x;
10+
let xraw: *mut i32 = unsafe { mem::transmute_copy(&xref) };
11+
let xshr = &*xref;
12+
// transmute fn ptr around so that we can avoid retagging
13+
let safe_raw: fn(x: *const i32, y: *mut i32) = unsafe {
14+
mem::transmute::<fn(&i32, &mut i32), _>(safe)
15+
};
16+
safe_raw(xshr, xraw);
1217
}
Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
// ignore-test validation_op is disabled
2-
31
#![allow(unused_variables)]
42

5-
mod safe {
6-
pub fn safe(x: &mut i32, y: &i32) {} //~ ERROR: in conflict with lock WriteLock
7-
}
3+
use std::mem;
4+
5+
pub fn safe(x: &mut i32, y: &i32) {} //~ ERROR does not exist on the stack
86

97
fn main() {
10-
let x = &mut 0 as *mut _;
11-
unsafe { safe::safe(&mut *x, &*x) };
8+
let mut x = 0;
9+
let xref = &mut x;
10+
let xraw: *mut i32 = unsafe { mem::transmute_copy(&xref) };
11+
let xshr = &*xref;
12+
// transmute fn ptr around so that we can avoid retagging
13+
let safe_raw: fn(x: *mut i32, y: *const i32) = unsafe {
14+
mem::transmute::<fn(&mut i32, &i32), _>(safe)
15+
};
16+
safe_raw(xraw, xshr);
1217
}
Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
// ignore-test validation_op is disabled
2-
31
#![allow(unused_variables)]
42

5-
mod safe {
6-
use std::cell::Cell;
3+
use std::mem;
4+
use std::cell::Cell;
75

8-
// Make sure &mut UnsafeCell also has a lock to it
9-
pub fn safe(x: &mut Cell<i32>, y: &i32) {} //~ ERROR: in conflict with lock WriteLock
10-
}
6+
// Make sure &mut UnsafeCell also is exclusive
7+
pub fn safe(x: &i32, y: &mut Cell<i32>) {} //~ ERROR barrier
118

129
fn main() {
13-
let x = &mut 0 as *mut _;
14-
unsafe { safe::safe(&mut *(x as *mut _), &*x) };
10+
let mut x = 0;
11+
let xref = &mut x;
12+
let xraw: *mut i32 = unsafe { mem::transmute_copy(&xref) };
13+
let xshr = &*xref;
14+
// transmute fn ptr around so that we can avoid retagging
15+
let safe_raw: fn(x: *const i32, y: *mut Cell<i32>) = unsafe {
16+
mem::transmute::<fn(&i32, &mut Cell<i32>), _>(safe)
17+
};
18+
safe_raw(xshr, xraw as *mut _);
1519
}

tests/compile-fail-fullmir/stacked_borrows/box_exclusive_violation1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn demo_mut_advanced_unique(mut our: Box<i32>) -> i32 {
88
unknown_code_2();
99

1010
// We know this will return 5
11-
*our //~ ERROR does not exist on the stack
11+
*our
1212
}
1313

1414
// Now comes the evil context
@@ -21,7 +21,7 @@ fn unknown_code_1(x: &i32) { unsafe {
2121
} }
2222

2323
fn unknown_code_2() { unsafe {
24-
*LEAK = 7;
24+
*LEAK = 7; //~ ERROR barrier
2525
} }
2626

2727
fn main() {
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
fn evil(x: &u32) {
2-
// mutating shared ref without `UnsafeCell`
3-
let x : *mut u32 = x as *const _ as *mut _;
4-
unsafe { *x = 42; }
5-
}
6-
71
fn main() {
82
let target = Box::new(42); // has an implicit raw
9-
let ref_ = &*target;
10-
evil(ref_); // invalidates shared ref, activates raw
11-
let _x = *ref_; //~ ERROR is not frozen
3+
let xref = &*target;
4+
{
5+
let x : *mut u32 = xref as *const _ as *mut _;
6+
unsafe { *x = 42; } // invalidates shared ref, activates raw
7+
}
8+
let _x = *xref; //~ ERROR is not frozen
129
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn inner(x: *mut i32, _y: &mut i32) {
2+
// If `x` and `y` alias, retagging is fine with this... but we really
3+
// shouldn't be allowed to use `x` at all because `y` was assumed to be
4+
// unique for the duration of this call.
5+
let _val = unsafe { *x }; //~ ERROR barrier
6+
}
7+
8+
fn main() {
9+
let mut x = 0;
10+
let xraw = &mut x as *mut _;
11+
let xref = unsafe { &mut *xraw };
12+
inner(xraw, xref);
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn inner(x: *mut i32, _y: &i32) {
2+
// If `x` and `y` alias, retagging is fine with this... but we really
3+
// shouldn't be allowed to write to `x` at all because `y` was assumed to be
4+
// immutable for the duration of this call.
5+
unsafe { *x = 0 }; //~ ERROR barrier
6+
}
7+
8+
fn main() {
9+
let mut x = 0;
10+
let xraw = &mut x as *mut _;
11+
let xref = unsafe { &*xraw };
12+
inner(xraw, xref);
13+
}

tests/compile-fail-fullmir/stacked_borrows/mut_exclusive_violation1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn unknown_code_1(x: &i32) { unsafe {
2121
} }
2222

2323
fn unknown_code_2() { unsafe {
24-
*LEAK = 7; //~ ERROR does not exist on the stack
24+
*LEAK = 7; //~ ERROR barrier
2525
} }
2626

2727
fn main() {

0 commit comments

Comments
 (0)