1
Fork 0

Adjust borrow checker algorithm to address #4856 unsoundness,

and then adjust code to match. rs=unsound (will review post-landing)
This commit is contained in:
Niko Matsakis 2013-02-08 22:21:45 -08:00
parent 91c59f5c9a
commit ab2534974c
25 changed files with 1046 additions and 575 deletions

View file

@ -184,25 +184,30 @@ impl<T: Owned> &MutexARC<T> {
*/
#[inline(always)]
unsafe fn access<U>(blk: fn(x: &mut T) -> U) -> U {
let state = unsafe { get_shared_mutable_state(&self.x) };
// Borrowck would complain about this if the function were not already
// unsafe. See borrow_rwlock, far below.
do (&state.lock).lock {
check_poison(true, state.failed);
let _z = PoisonOnFail(&mut state.failed);
blk(&mut state.data)
unsafe {
let state = get_shared_mutable_state(&self.x);
// Borrowck would complain about this if the function were
// not already unsafe. See borrow_rwlock, far below.
do (&(*state).lock).lock {
check_poison(true, (*state).failed);
let _z = PoisonOnFail(&mut (*state).failed);
blk(&mut (*state).data)
}
}
}
/// As access(), but with a condvar, as sync::mutex.lock_cond().
#[inline(always)]
unsafe fn access_cond<U>(blk: fn(x: &x/mut T, c: &c/Condvar) -> U) -> U {
let state = unsafe { get_shared_mutable_state(&self.x) };
do (&state.lock).lock_cond |cond| {
check_poison(true, state.failed);
let _z = PoisonOnFail(&mut state.failed);
blk(&mut state.data,
&Condvar { is_mutex: true, failed: &mut state.failed,
cond: cond })
unsafe {
let state = get_shared_mutable_state(&self.x);
do (&(*state).lock).lock_cond |cond| {
check_poison(true, (*state).failed);
let _z = PoisonOnFail(&mut (*state).failed);
blk(&mut (*state).data,
&Condvar {is_mutex: true,
failed: &mut (*state).failed,
cond: cond })
}
}
}
}
@ -285,8 +290,10 @@ pub fn RWARC<T: Const Owned>(user_data: T) -> RWARC<T> {
* Create a reader/writer ARC with the supplied data and a specified number
* of condvars (as sync::rwlock_with_condvars).
*/
pub fn rw_arc_with_condvars<T: Const Owned>(user_data: T,
num_condvars: uint) -> RWARC<T> {
pub fn rw_arc_with_condvars<T: Const Owned>(
user_data: T,
num_condvars: uint) -> RWARC<T>
{
let data =
RWARCInner { lock: rwlock_with_condvars(num_condvars),
failed: false, data: move user_data };
@ -315,23 +322,28 @@ impl<T: Const Owned> &RWARC<T> {
*/
#[inline(always)]
fn write<U>(blk: fn(x: &mut T) -> U) -> U {
let state = unsafe { get_shared_mutable_state(&self.x) };
do borrow_rwlock(state).write {
check_poison(false, state.failed);
let _z = PoisonOnFail(&mut state.failed);
blk(&mut state.data)
unsafe {
let state = get_shared_mutable_state(&self.x);
do (*borrow_rwlock(state)).write {
check_poison(false, (*state).failed);
let _z = PoisonOnFail(&mut (*state).failed);
blk(&mut (*state).data)
}
}
}
/// As write(), but with a condvar, as sync::rwlock.write_cond().
#[inline(always)]
fn write_cond<U>(blk: fn(x: &x/mut T, c: &c/Condvar) -> U) -> U {
let state = unsafe { get_shared_mutable_state(&self.x) };
do borrow_rwlock(state).write_cond |cond| {
check_poison(false, state.failed);
let _z = PoisonOnFail(&mut state.failed);
blk(&mut state.data,
&Condvar { is_mutex: false, failed: &mut state.failed,
cond: cond })
unsafe {
let state = get_shared_mutable_state(&self.x);
do (*borrow_rwlock(state)).write_cond |cond| {
check_poison(false, (*state).failed);
let _z = PoisonOnFail(&mut (*state).failed);
blk(&mut (*state).data,
&Condvar {is_mutex: false,
failed: &mut (*state).failed,
cond: cond})
}
}
}
/**
@ -369,11 +381,14 @@ impl<T: Const Owned> &RWARC<T> {
* ~~~
*/
fn write_downgrade<U>(blk: fn(v: RWWriteMode<T>) -> U) -> U {
let state = unsafe { get_shared_mutable_state(&self.x) };
do borrow_rwlock(state).write_downgrade |write_mode| {
check_poison(false, state.failed);
blk(RWWriteMode((&mut state.data, move write_mode,
PoisonOnFail(&mut state.failed))))
unsafe {
let state = get_shared_mutable_state(&self.x);
do (*borrow_rwlock(state)).write_downgrade |write_mode| {
check_poison(false, (*state).failed);
blk(RWWriteMode((&mut (*state).data,
move write_mode,
PoisonOnFail(&mut (*state).failed))))
}
}
}
@ -417,8 +432,8 @@ pub fn unwrap_rw_arc<T: Const Owned>(arc: RWARC<T>) -> T {
// lock it. This wraps the unsafety, with the justification that the 'lock'
// field is never overwritten; only 'failed' and 'data'.
#[doc(hidden)]
fn borrow_rwlock<T: Const Owned>(state: &r/mut RWARCInner<T>) -> &r/RWlock {
unsafe { cast::transmute(&mut state.lock) }
fn borrow_rwlock<T: Const Owned>(state: *const RWARCInner<T>) -> *RWlock {
unsafe { cast::transmute(&const (*state).lock) }
}
// FIXME (#3154) ice with struct/&<T> prevents these from being structs.