From 1c365cedf8933c42538a6707999fec7f466e834a Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 15 Mar 2019 12:03:10 +0100 Subject: [PATCH 1/4] Revert "Remove RefCell::borrow_state" This reverts commit 313aab8fbeb98730f8ffa741ccf54f843d5e3525. --- .../src/library-features/borrow-state.md | 7 +++ src/libcore/cell.rs | 49 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/borrow-state.md diff --git a/src/doc/unstable-book/src/library-features/borrow-state.md b/src/doc/unstable-book/src/library-features/borrow-state.md new file mode 100644 index 0000000000000..304b8dffe9867 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/borrow-state.md @@ -0,0 +1,7 @@ +# `borrow_state` + +The tracking issue for this feature is: [#27733] + +[#27733]: https://github.com/rust-lang/rust/issues/27733 + +------------------------ diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 8383d305518ab..64c63e5ce1a54 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -569,6 +569,20 @@ pub struct RefCell { value: UnsafeCell, } +/// An enumeration of values returned from the `state` method on a `RefCell`. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[unstable(feature = "borrow_state", issue = "27733")] +#[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")] +#[allow(deprecated)] +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, +} + /// An error returned by [`RefCell::try_borrow`](struct.RefCell.html#method.try_borrow). #[stable(feature = "try_borrow", since = "1.13.0")] pub struct BorrowError { @@ -753,6 +767,41 @@ impl RefCell { } impl RefCell { + /// 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. + /// + /// # Examples + /// + /// ``` + /// #![feature(borrow_state)] + /// + /// use std::cell::{BorrowState, RefCell}; + /// + /// let c = RefCell::new(5); + /// + /// match c.borrow_state() { + /// BorrowState::Writing => println!("Cannot be borrowed"), + /// BorrowState::Reading => println!("Cannot be borrowed mutably"), + /// BorrowState::Unused => println!("Can be borrowed (mutably as well)"), + /// } + /// ``` + #[unstable(feature = "borrow_state", issue = "27733")] + #[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")] + #[allow(deprecated)] + #[inline] + pub fn borrow_state(&self) -> BorrowState { + let borrow = self.borrow.get(); + if is_writing(borrow) { + BorrowState::Writing + } else if is_reading(borrow) { + BorrowState::Reading + } else { + BorrowState::Unused + } + } + /// Immutably borrows the wrapped value. /// /// The borrow lasts until the returned `Ref` exits scope. Multiple From fab71dd0469840c349c236d8c3caa89fbbfb8fc5 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 15 Mar 2019 12:03:59 +0100 Subject: [PATCH 2/4] Revert "Deprecate std::cell::RefCell::borrow_state" This reverts commit dc2d5058e999abb18ab2686b4e3e385ec6e36666. --- src/libcore/cell.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 64c63e5ce1a54..c7bbf02fc1871 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -572,8 +572,6 @@ pub struct RefCell { /// An enumeration of values returned from the `state` method on a `RefCell`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[unstable(feature = "borrow_state", issue = "27733")] -#[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")] -#[allow(deprecated)] pub enum BorrowState { /// The cell is currently being read, there is at least one active `borrow`. Reading, @@ -788,8 +786,6 @@ impl RefCell { /// } /// ``` #[unstable(feature = "borrow_state", issue = "27733")] - #[rustc_deprecated(since = "1.15.0", reason = "use `try_borrow` instead")] - #[allow(deprecated)] #[inline] pub fn borrow_state(&self) -> BorrowState { let borrow = self.borrow.get(); From a9388c28c2a6cfb82724612b4d3601475dee9325 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 16 Mar 2019 12:16:25 +0100 Subject: [PATCH 3/4] Tweak documentation of RefCell::borrow_state --- src/libcore/cell.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c7bbf02fc1871..fe5cc8bd2740d 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -765,10 +765,14 @@ impl RefCell { } impl RefCell { - /// Query the current state of this `RefCell` + /// Queries 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. + /// A return value of `BorrowState::Writing` signals that this `RefCell` + /// is currently mutably borrowed, while `BorrowState::Reading` signals + /// that it is immutably borrowed. + /// + /// This is mostly useful in rare use cases with `RefCell::as_ptr` to + /// access the data without changing its borrow state, use with care. /// /// # Examples /// @@ -780,9 +784,9 @@ impl RefCell { /// let c = RefCell::new(5); /// /// match c.borrow_state() { - /// BorrowState::Writing => println!("Cannot be borrowed"), - /// BorrowState::Reading => println!("Cannot be borrowed mutably"), - /// BorrowState::Unused => println!("Can be borrowed (mutably as well)"), + /// BorrowState::Writing => println!("currently borrowed mutably"), + /// BorrowState::Reading => println!("currently borrowed immutably"), + /// BorrowState::Unused => println!("not borrowed"), /// } /// ``` #[unstable(feature = "borrow_state", issue = "27733")] From 38811a1d31beac00e4b7c331341f557a3de2151a Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 19 Mar 2019 12:24:38 +0100 Subject: [PATCH 4/4] Introduce RefCell::try_borrow_unguarded This replaces RefCell::borrow_state to something that encodes the use case of Servo better. --- src/libcore/cell.rs | 87 ++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index fe5cc8bd2740d..c67ac26562f13 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -569,18 +569,6 @@ pub struct RefCell { value: UnsafeCell, } -/// An enumeration of values returned from the `state` method on a `RefCell`. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -#[unstable(feature = "borrow_state", issue = "27733")] -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, -} - /// An error returned by [`RefCell::try_borrow`](struct.RefCell.html#method.try_borrow). #[stable(feature = "try_borrow", since = "1.13.0")] pub struct BorrowError { @@ -765,43 +753,6 @@ impl RefCell { } impl RefCell { - /// Queries the current state of this `RefCell`. - /// - /// A return value of `BorrowState::Writing` signals that this `RefCell` - /// is currently mutably borrowed, while `BorrowState::Reading` signals - /// that it is immutably borrowed. - /// - /// This is mostly useful in rare use cases with `RefCell::as_ptr` to - /// access the data without changing its borrow state, use with care. - /// - /// # Examples - /// - /// ``` - /// #![feature(borrow_state)] - /// - /// use std::cell::{BorrowState, RefCell}; - /// - /// let c = RefCell::new(5); - /// - /// match c.borrow_state() { - /// BorrowState::Writing => println!("currently borrowed mutably"), - /// BorrowState::Reading => println!("currently borrowed immutably"), - /// BorrowState::Unused => println!("not borrowed"), - /// } - /// ``` - #[unstable(feature = "borrow_state", issue = "27733")] - #[inline] - pub fn borrow_state(&self) -> BorrowState { - let borrow = self.borrow.get(); - if is_writing(borrow) { - BorrowState::Writing - } else if is_reading(borrow) { - BorrowState::Reading - } else { - BorrowState::Unused - } - } - /// Immutably borrows the wrapped value. /// /// The borrow lasts until the returned `Ref` exits scope. Multiple @@ -1007,6 +958,44 @@ impl RefCell { &mut *self.value.get() } } + + /// Immutably borrows the wrapped value, returning an error if the value is + /// currently mutably borrowed. + /// + /// # Safety + /// + /// Unlike `RefCell::borrow`, this method is unsafe because it does not + /// return a `Ref`, thus leaving the borrow flag untouched. Mutably + /// borrowing the `RefCell` while the reference returned by this method + /// is alive is undefined behaviour. + /// + /// # Examples + /// + /// ``` + /// #![feature(borrow_state)] + /// use std::cell::RefCell; + /// + /// let c = RefCell::new(5); + /// + /// { + /// let m = c.borrow_mut(); + /// assert!(unsafe { c.try_borrow_unguarded() }.is_err()); + /// } + /// + /// { + /// let m = c.borrow(); + /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok()); + /// } + /// ``` + #[unstable(feature = "borrow_state", issue = "27733")] + #[inline] + pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { + if !is_writing(self.borrow.get()) { + Ok(&*self.value.get()) + } else { + Err(BorrowError { _private: () }) + } + } } #[stable(feature = "rust1", since = "1.0.0")]