diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 8a2c6acf0257b..a20f8923e9411 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -555,6 +555,33 @@ pub fn clone_ref<'b, T: ?Sized>(orig: &Ref<'b, T>) -> Ref<'b, T> { } } +/// Make a new `Ref` for a component of the borrowed data, e.g. an enum variant. +/// +/// The `RefCell` is already immutably borrowed, so this cannot fail. +/// +/// A method would interfere with methods of the same name on the contents of a `RefCell` +/// used through `Deref`. +/// +/// # Example +/// +/// ``` +/// use std::cell::{RefCell, Ref, map_ref}; +/// +/// let c = RefCell::new(Some(5)); +/// let b1: Ref> = c.borrow(); +/// let b2: Ref = map_ref(&b1, (*b1).as_ref().unwrap()); +/// assert_eq!(*b2, 5); +/// ``` +#[unstable(feature = "core", + reason = "recently added")] +#[inline] +pub fn map_ref<'b, T: ?Sized, U: ?Sized>(orig: &Ref<'b, T>, new: &'b U) -> Ref<'b, U> { + Ref { + _value: new, + _borrow: orig._borrow.clone(), + } +} + struct BorrowRefMut<'b> { _borrow: &'b Cell, } diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index f02312b8641e1..3b41379e8bb73 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -129,6 +129,22 @@ fn clone_ref_updates_flag() { assert_eq!(x.borrow_state(), BorrowState::Unused); } +#[test] +fn map_ref_updates_flag() { + let x = RefCell::new(Some(5)); + { + let b1: Ref> = x.borrow(); + assert_eq!(x.borrow_state(), BorrowState::Reading); + { + let b2: Ref = map_ref(&b1, b1.as_ref().unwrap()); + assert_eq!(*b2, 5); + assert_eq!(x.borrow_state(), BorrowState::Reading); + } + assert_eq!(x.borrow_state(), BorrowState::Reading); + } + assert_eq!(x.borrow_state(), BorrowState::Unused); +} + #[test] fn as_unsafe_cell() { let c1: Cell = Cell::new(0);