Skip to content

std: Deprecate RefCell::{try_borrow, try_borrow_mut} #21854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 45 additions & 10 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,18 @@ pub struct RefCell<T> {
borrow: Cell<BorrowFlag>,
}

/// An enumeration of values returned from the `state` method on a `RefCell<T>`.
#[derive(Copy, Clone, PartialEq)]
#[unstable(feature = "std_misc")]
pub enum BorrowState {
/// The cell is currently being read, there is at least one active `borrow`.
Reading,
/// The cell is currently being written to, there is an active `borrow_mut`.
Writing,
/// There are no outstanding borrows on this cell.
Unused,
}

// Values [1, MAX-1] represent the number of `Ref` active
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
Expand Down Expand Up @@ -310,13 +322,28 @@ impl<T> RefCell<T> {
unsafe { self.value.into_inner() }
}

/// Query the current state of this `RefCell`
///
/// The returned value can be dispatched on to determine if a call to
/// `borrow` or `borrow_mut` would succeed.
#[unstable(feature = "std_misc")]
pub fn borrow_state(&self) -> BorrowState {
match self.borrow.get() {
WRITING => BorrowState::Writing,
UNUSED => BorrowState::Unused,
_ => BorrowState::Reading,
}
}

/// Attempts to immutably borrow the wrapped value.
///
/// The borrow lasts until the returned `Ref` exits scope. Multiple
/// immutable borrows can be taken out at the same time.
///
/// Returns `None` if the value is currently mutably borrowed.
#[unstable(feature = "core", reason = "may be renamed or removed")]
#[deprecated(since = "1.0.0",
reason = "dispatch on `cell.borrow_state()` instead")]
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
match BorrowRef::new(&self.borrow) {
Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
Expand All @@ -326,8 +353,8 @@ impl<T> RefCell<T> {

/// Immutably borrows the wrapped value.
///
/// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be
/// taken out at the same time.
/// The borrow lasts until the returned `Ref` exits scope. Multiple
/// immutable borrows can be taken out at the same time.
///
/// # Panics
///
Expand Down Expand Up @@ -361,9 +388,12 @@ impl<T> RefCell<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
match self.try_borrow() {
Some(ptr) => ptr,
None => panic!("RefCell<T> already mutably borrowed")
match BorrowRef::new(&self.borrow) {
Some(b) => Ref {
_value: unsafe { &*self.value.get() },
_borrow: b,
},
None => panic!("RefCell<T> already mutably borrowed"),
}
}

Expand All @@ -374,6 +404,8 @@ impl<T> RefCell<T> {
///
/// Returns `None` if the value is currently borrowed.
#[unstable(feature = "core", reason = "may be renamed or removed")]
#[deprecated(since = "1.0.0",
reason = "dispatch on `cell.borrow_state()` instead")]
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
match BorrowRefMut::new(&self.borrow) {
Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }),
Expand All @@ -383,8 +415,8 @@ impl<T> RefCell<T> {

/// Mutably borrows the wrapped value.
///
/// The borrow lasts until the returned `RefMut` exits scope. The value cannot be borrowed
/// while this borrow is active.
/// The borrow lasts until the returned `RefMut` exits scope. The value
/// cannot be borrowed while this borrow is active.
///
/// # Panics
///
Expand Down Expand Up @@ -417,9 +449,12 @@ impl<T> RefCell<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
match self.try_borrow_mut() {
Some(ptr) => ptr,
None => panic!("RefCell<T> already borrowed")
match BorrowRefMut::new(&self.borrow) {
Some(b) => RefMut {
_value: unsafe { &mut *self.value.get() },
_borrow: b,
},
None => panic!("RefCell<T> already borrowed"),
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#![stable(feature = "rust1", since = "1.0.0")]

use any;
use cell::{Cell, RefCell, Ref, RefMut};
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
use char::CharExt;
use iter::{Iterator, IteratorExt};
use marker::{Copy, Sized};
Expand Down Expand Up @@ -973,9 +973,11 @@ impl<T: Copy + Debug> Debug for Cell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Debug> Debug for RefCell<T> {
fn fmt(&self, f: &mut Formatter) -> Result {
match self.try_borrow() {
Some(val) => write!(f, "RefCell {{ value: {:?} }}", val),
None => write!(f, "RefCell {{ <borrowed> }}")
match self.borrow_state() {
BorrowState::Unused | BorrowState::Reading => {
write!(f, "RefCell {{ value: {:?} }}", self.borrow())
}
BorrowState::Writing => write!(f, "RefCell {{ <borrowed> }}"),
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/libcoretest/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,24 @@ fn no_mut_then_imm_borrow() {
let x = RefCell::new(0);
let _b1 = x.borrow_mut();
assert!(x.try_borrow().is_none());
assert_eq!(x.borrow_state(), BorrowState::Writing);
}

#[test]
fn no_imm_then_borrow_mut() {
let x = RefCell::new(0);
let _b1 = x.borrow();
assert!(x.try_borrow_mut().is_none());
assert_eq!(x.borrow_state(), BorrowState::Reading);
}

#[test]
fn no_double_borrow_mut() {
let x = RefCell::new(0);
assert_eq!(x.borrow_state(), BorrowState::Unused);
let _b1 = x.borrow_mut();
assert!(x.try_borrow_mut().is_none());
assert_eq!(x.borrow_state(), BorrowState::Writing);
}

#[test]
Expand Down