Skip to content

Commit 87eb67f

Browse files
committed
rollup merge of rust-lang#21854: alexcrichton/try-borrow
The existence of these two functions is at odds with our current [error conventions][conventions] which recommend that panicking and `Result`-like variants should not be provided together. [conventions]: https://github.com/rust-lang/rfcs/blob/master/text/0236-error-conventions.md#do-not-provide-both-result-and-fail-variants This commit adds a new `borrow_state` function returning a `BorrowState` enum to `RefCell` which serves as a replacemnt for the `try_borrow` and `try_borrow_mut` functions.
2 parents 0a10e32 + deed093 commit 87eb67f

File tree

3 files changed

+55
-14
lines changed

3 files changed

+55
-14
lines changed

src/libcore/cell.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,18 @@ pub struct RefCell<T> {
266266
borrow: Cell<BorrowFlag>,
267267
}
268268

269+
/// An enumeration of values returned from the `state` method on a `RefCell<T>`.
270+
#[derive(Copy, Clone, PartialEq)]
271+
#[unstable(feature = "std_misc")]
272+
pub enum BorrowState {
273+
/// The cell is currently being read, there is at least one active `borrow`.
274+
Reading,
275+
/// The cell is currently being written to, there is an active `borrow_mut`.
276+
Writing,
277+
/// There are no outstanding borrows on this cell.
278+
Unused,
279+
}
280+
269281
// Values [1, MAX-1] represent the number of `Ref` active
270282
// (will not outgrow its range since `uint` is the size of the address space)
271283
type BorrowFlag = uint;
@@ -310,13 +322,28 @@ impl<T> RefCell<T> {
310322
unsafe { self.value.into_inner() }
311323
}
312324

325+
/// Query the current state of this `RefCell`
326+
///
327+
/// The returned value can be dispatched on to determine if a call to
328+
/// `borrow` or `borrow_mut` would succeed.
329+
#[unstable(feature = "std_misc")]
330+
pub fn borrow_state(&self) -> BorrowState {
331+
match self.borrow.get() {
332+
WRITING => BorrowState::Writing,
333+
UNUSED => BorrowState::Unused,
334+
_ => BorrowState::Reading,
335+
}
336+
}
337+
313338
/// Attempts to immutably borrow the wrapped value.
314339
///
315340
/// The borrow lasts until the returned `Ref` exits scope. Multiple
316341
/// immutable borrows can be taken out at the same time.
317342
///
318343
/// Returns `None` if the value is currently mutably borrowed.
319344
#[unstable(feature = "core", reason = "may be renamed or removed")]
345+
#[deprecated(since = "1.0.0",
346+
reason = "dispatch on `cell.borrow_state()` instead")]
320347
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
321348
match BorrowRef::new(&self.borrow) {
322349
Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
@@ -326,8 +353,8 @@ impl<T> RefCell<T> {
326353

327354
/// Immutably borrows the wrapped value.
328355
///
329-
/// The borrow lasts until the returned `Ref` exits scope. Multiple immutable borrows can be
330-
/// taken out at the same time.
356+
/// The borrow lasts until the returned `Ref` exits scope. Multiple
357+
/// immutable borrows can be taken out at the same time.
331358
///
332359
/// # Panics
333360
///
@@ -361,9 +388,12 @@ impl<T> RefCell<T> {
361388
/// ```
362389
#[stable(feature = "rust1", since = "1.0.0")]
363390
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
364-
match self.try_borrow() {
365-
Some(ptr) => ptr,
366-
None => panic!("RefCell<T> already mutably borrowed")
391+
match BorrowRef::new(&self.borrow) {
392+
Some(b) => Ref {
393+
_value: unsafe { &*self.value.get() },
394+
_borrow: b,
395+
},
396+
None => panic!("RefCell<T> already mutably borrowed"),
367397
}
368398
}
369399

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

384416
/// Mutably borrows the wrapped value.
385417
///
386-
/// The borrow lasts until the returned `RefMut` exits scope. The value cannot be borrowed
387-
/// while this borrow is active.
418+
/// The borrow lasts until the returned `RefMut` exits scope. The value
419+
/// cannot be borrowed while this borrow is active.
388420
///
389421
/// # Panics
390422
///
@@ -417,9 +449,12 @@ impl<T> RefCell<T> {
417449
/// ```
418450
#[stable(feature = "rust1", since = "1.0.0")]
419451
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
420-
match self.try_borrow_mut() {
421-
Some(ptr) => ptr,
422-
None => panic!("RefCell<T> already borrowed")
452+
match BorrowRefMut::new(&self.borrow) {
453+
Some(b) => RefMut {
454+
_value: unsafe { &mut *self.value.get() },
455+
_borrow: b,
456+
},
457+
None => panic!("RefCell<T> already borrowed"),
423458
}
424459
}
425460

src/libcore/fmt/mod.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414

1515
use any;
16-
use cell::{Cell, RefCell, Ref, RefMut};
16+
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
1717
use char::CharExt;
1818
use iter::{Iterator, IteratorExt};
1919
use marker::{Copy, Sized};
@@ -920,9 +920,11 @@ impl<T: Copy + Debug> Debug for Cell<T> {
920920
#[stable(feature = "rust1", since = "1.0.0")]
921921
impl<T: Debug> Debug for RefCell<T> {
922922
fn fmt(&self, f: &mut Formatter) -> Result {
923-
match self.try_borrow() {
924-
Some(val) => write!(f, "RefCell {{ value: {:?} }}", val),
925-
None => write!(f, "RefCell {{ <borrowed> }}")
923+
match self.borrow_state() {
924+
BorrowState::Unused | BorrowState::Reading => {
925+
write!(f, "RefCell {{ value: {:?} }}", self.borrow())
926+
}
927+
BorrowState::Writing => write!(f, "RefCell {{ <borrowed> }}"),
926928
}
927929
}
928930
}

src/libcoretest/cell.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,24 @@ fn no_mut_then_imm_borrow() {
6060
let x = RefCell::new(0);
6161
let _b1 = x.borrow_mut();
6262
assert!(x.try_borrow().is_none());
63+
assert_eq!(x.borrow_state(), BorrowState::Writing);
6364
}
6465

6566
#[test]
6667
fn no_imm_then_borrow_mut() {
6768
let x = RefCell::new(0);
6869
let _b1 = x.borrow();
6970
assert!(x.try_borrow_mut().is_none());
71+
assert_eq!(x.borrow_state(), BorrowState::Reading);
7072
}
7173

7274
#[test]
7375
fn no_double_borrow_mut() {
7476
let x = RefCell::new(0);
77+
assert_eq!(x.borrow_state(), BorrowState::Unused);
7578
let _b1 = x.borrow_mut();
7679
assert!(x.try_borrow_mut().is_none());
80+
assert_eq!(x.borrow_state(), BorrowState::Writing);
7781
}
7882

7983
#[test]

0 commit comments

Comments
 (0)