Rollup merge of #118087 - GrigorenkoPV:refcell_try_map, r=Mark-Simula… · jieyouxu/rust@324bf2b (original) (raw)

`@@ -1573,6 +1573,47 @@ impl<'b, T: ?Sized> Ref<'b, T> {

`

1573

1573

`}

`

1574

1574

`}

`

1575

1575

``

``

1576

`` +

/// Tries to makes a new Ref for a component of the borrowed data.

``

``

1577

`+

/// On failure, the original guard is returned alongside with the error

`

``

1578

`+

/// returned by the closure.

`

``

1579

`+

///

`

``

1580

`` +

/// The RefCell is already immutably borrowed, so this cannot fail.

``

``

1581

`+

///

`

``

1582

`+

/// This is an associated function that needs to be used as

`

``

1583

`` +

/// Ref::try_map(...). A method would interfere with methods of the same

``

``

1584

`` +

/// name on the contents of a RefCell used through Deref.

``

``

1585

`+

///

`

``

1586

`+

/// # Examples

`

``

1587

`+

///

`

``

1588


/// ```

``

1589

`+

/// #![feature(refcell_try_map)]

`

``

1590

`+

/// use std::cell::{RefCell, Ref};

`

``

1591

`+

/// use std::str::{from_utf8, Utf8Error};

`

``

1592

`+

///

`

``

1593

`+

/// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6 ,0x80]);

`

``

1594

`+

/// let b1: Ref<'_, Vec> = c.borrow();

`

``

1595

`+

/// let b2: Result<Ref<'_, str>, _> = Ref::try_map(b1, |v| from_utf8(v));

`

``

1596

`+

/// assert_eq!(&*b2.unwrap(), "🦀");

`

``

1597

`+

///

`

``

1598

`+

/// let c = RefCell::new(vec![0xF0, 0x9F, 0xA6]);

`

``

1599

`+

/// let b1: Ref<'_, Vec> = c.borrow();

`

``

1600

`+

/// let b2: Result<_, (Ref<'_, Vec>, Utf8Error)> = Ref::try_map(b1, |v| from_utf8(v));

`

``

1601

`+

/// let (b3, e) = b2.unwrap_err();

`

``

1602

`+

/// assert_eq!(*b3, vec![0xF0, 0x9F, 0xA6]);

`

``

1603

`+

/// assert_eq!(e.valid_up_to(), 0);

`

``

1604


/// ```

``

1605

`+

#[unstable(feature = "refcell_try_map", issue = "143801")]

`

``

1606

`+

#[inline]

`

``

1607

`+

pub fn try_map<U: ?Sized, E>(

`

``

1608

`+

orig: Ref<'b, T>,

`

``

1609

`+

f: impl FnOnce(&T) -> Result<&U, E>,

`

``

1610

`+

) -> Result<Ref<'b, U>, (Self, E)> {

`

``

1611

`+

match f(&*orig) {

`

``

1612

`+

Ok(value) => Ok(Ref { value: NonNull::from(value), borrow: orig.borrow }),

`

``

1613

`+

Err(e) => Err((orig, e)),

`

``

1614

`+

}

`

``

1615

`+

}

`

``

1616

+

1576

1617

`` /// Splits a Ref into multiple Refs for different components of the

``

1577

1618

`/// borrowed data.

`

1578

1619

`///

`

`@@ -1734,6 +1775,58 @@ impl<'b, T: ?Sized> RefMut<'b, T> {

`

1734

1775

`}

`

1735

1776

`}

`

1736

1777

``

``

1778

`` +

/// Tries to makes a new RefMut for a component of the borrowed data.

``

``

1779

`+

/// On failure, the original guard is returned alongside with the error

`

``

1780

`+

/// returned by the closure.

`

``

1781

`+

///

`

``

1782

`` +

/// The RefCell is already mutably borrowed, so this cannot fail.

``

``

1783

`+

///

`

``

1784

`+

/// This is an associated function that needs to be used as

`

``

1785

`` +

/// RefMut::try_map(...). A method would interfere with methods of the same

``

``

1786

`` +

/// name on the contents of a RefCell used through Deref.

``

``

1787

`+

///

`

``

1788

`+

/// # Examples

`

``

1789

`+

///

`

``

1790


/// ```

``

1791

`+

/// #![feature(refcell_try_map)]

`

``

1792

`+

/// use std::cell::{RefCell, RefMut};

`

``

1793

`+

/// use std::str::{from_utf8_mut, Utf8Error};

`

``

1794

`+

///

`

``

1795

`+

/// let c = RefCell::new(vec![0x68, 0x65, 0x6C, 0x6C, 0x6F]);

`

``

1796

`+

/// {

`

``

1797

`+

/// let b1: RefMut<'_, Vec> = c.borrow_mut();

`

``

1798

`+

/// let b2: Result<RefMut<'_, str>, _> = RefMut::try_map(b1, |v| from_utf8_mut(v));

`

``

1799

`+

/// let mut b2 = b2.unwrap();

`

``

1800

`+

/// assert_eq!(&*b2, "hello");

`

``

1801

`+

/// b2.make_ascii_uppercase();

`

``

1802

`+

/// }

`

``

1803

`+

/// assert_eq!(*c.borrow(), "HELLO".as_bytes());

`

``

1804

`+

///

`

``

1805

`+

/// let c = RefCell::new(vec![0xFF]);

`

``

1806

`+

/// let b1: RefMut<'_, Vec> = c.borrow_mut();

`

``

1807

`+

/// let b2: Result<_, (RefMut<'_, Vec>, Utf8Error)> = RefMut::try_map(b1, |v| from_utf8_mut(v));

`

``

1808

`+

/// let (b3, e) = b2.unwrap_err();

`

``

1809

`+

/// assert_eq!(*b3, vec![0xFF]);

`

``

1810

`+

/// assert_eq!(e.valid_up_to(), 0);

`

``

1811


/// ```

``

1812

`+

#[unstable(feature = "refcell_try_map", issue = "143801")]

`

``

1813

`+

#[inline]

`

``

1814

`+

pub fn try_map<U: ?Sized, E>(

`

``

1815

`+

mut orig: RefMut<'b, T>,

`

``

1816

`+

f: impl FnOnce(&mut T) -> Result<&mut U, E>,

`

``

1817

`+

) -> Result<RefMut<'b, U>, (Self, E)> {

`

``

1818

`+

// SAFETY: function holds onto an exclusive reference for the duration

`

``

1819

`` +

// of its call through orig, and the pointer is only de-referenced

``

``

1820

`+

// inside of the function call never allowing the exclusive reference to

`

``

1821

`+

// escape.

`

``

1822

`+

match f(&mut *orig) {

`

``

1823

`+

Ok(value) => {

`

``

1824

`+

Ok(RefMut { value: NonNull::from(value), borrow: orig.borrow, marker: PhantomData })

`

``

1825

`+

}

`

``

1826

`+

Err(e) => Err((orig, e)),

`

``

1827

`+

}

`

``

1828

`+

}

`

``

1829

+

1737

1830

`` /// Splits a RefMut into multiple RefMuts for different components of the

``

1738

1831

`/// borrowed data.

`

1739

1832

`///

`