Skip to content

Commit 0660b8b

Browse files
committed
Introduce {Ref, RefMut}::try_map for optional projections
1 parent 4e208f6 commit 0660b8b

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

library/core/src/cell.rs

+70
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,36 @@ impl<'b, T: ?Sized> Ref<'b, T> {
12611261
Ref { value: f(orig.value), borrow: orig.borrow }
12621262
}
12631263

1264+
/// Makes a new `Ref` for an optional component of the borrowed data.
1265+
///
1266+
/// The `RefCell` is already immutably borrowed, so this cannot fail.
1267+
///
1268+
/// This is an associated function that needs to be used as
1269+
/// `Ref::try_map(...)`. A method would interfere with methods of the same
1270+
/// name on the contents of a `RefCell` used through `Deref`.
1271+
///
1272+
/// # Examples
1273+
///
1274+
/// ```
1275+
/// #![feature(cell_try_map)]
1276+
///
1277+
/// use std::cell::{RefCell, Ref};
1278+
///
1279+
/// let c = RefCell::new(vec![1, 2, 3]);
1280+
/// let b1: Ref<Vec<u32>> = c.borrow();
1281+
/// let b2: Option<Ref<u32>> = Ref::try_map(b1, |v| v.get(1));
1282+
/// assert_eq!(b2.as_deref(), Some(&2))
1283+
/// ```
1284+
#[unstable(feature = "cell_try_map", reason = "recently added", issue = "none")]
1285+
#[inline]
1286+
pub fn try_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Option<Ref<'b, U>>
1287+
where
1288+
F: FnOnce(&T) -> Option<&U>,
1289+
{
1290+
let value = f(orig.value)?;
1291+
Some(Ref { value, borrow: orig.borrow })
1292+
}
1293+
12641294
/// Splits a `Ref` into multiple `Ref`s for different components of the
12651295
/// borrowed data.
12661296
///
@@ -1372,6 +1402,46 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
13721402
RefMut { value: f(value), borrow }
13731403
}
13741404

1405+
/// Makes a new `RefMut` for an optional component of the borrowed data.
1406+
///
1407+
/// The `RefCell` is already mutably borrowed, so this cannot fail.
1408+
///
1409+
/// This is an associated function that needs to be used as
1410+
/// `RefMut::try_map(...)`. A method would interfere with methods of the
1411+
/// same name on the contents of a `RefCell` used through `Deref`.
1412+
///
1413+
/// # Examples
1414+
///
1415+
/// ```
1416+
/// #![feature(cell_try_map)]
1417+
///
1418+
/// use std::cell::{RefCell, RefMut};
1419+
///
1420+
/// let c = RefCell::new(vec![1, 2, 3]);
1421+
///
1422+
/// {
1423+
/// let b1: RefMut<Vec<u32>> = c.borrow_mut();
1424+
/// let mut b2: Option<RefMut<u32>> = RefMut::try_map(b1, |v| v.get_mut(1));
1425+
///
1426+
/// if let Some(mut b2) = b2 {
1427+
/// *b2 += 2;
1428+
/// }
1429+
/// }
1430+
///
1431+
/// assert_eq!(*c.borrow(), vec![1, 4, 3]);
1432+
/// ```
1433+
#[unstable(feature = "cell_try_map", reason = "recently added", issue = "none")]
1434+
#[inline]
1435+
pub fn try_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Option<RefMut<'b, U>>
1436+
where
1437+
F: FnOnce(&mut T) -> Option<&mut U>,
1438+
{
1439+
// FIXME(nll-rfc#40): fix borrow-check
1440+
let RefMut { value, borrow } = orig;
1441+
let value = f(value)?;
1442+
Some(RefMut { value, borrow })
1443+
}
1444+
13751445
/// Splits a `RefMut` into multiple `RefMut`s for different components of the
13761446
/// borrowed data.
13771447
///

0 commit comments

Comments
 (0)