@@ -946,6 +946,55 @@ impl<'a, T: Trace + ?Sized, U: ?Sized> GcCellRefMut<'a, T, U> {
946946 value : f ( value) ,
947947 }
948948 }
949+
950+ /// Makes a new `GcCellRefMut` for an optional component of the borrowed
951+ /// data. The original guard is returned as an `Err(..)` if the closure
952+ /// returns `None`.
953+ ///
954+ /// The `GcCellRefMut` is already mutably borrowed, so this cannot fail.
955+ ///
956+ /// This is an associated function that needs to be used as
957+ /// `GcCellRefMut::filter_map(...)`. A method would interfere with methods
958+ /// of the same name on the contents of a `GcCell` used through `Deref`.
959+ ///
960+ /// # Examples
961+ ///
962+ /// ```
963+ /// use gc::{GcCell, GcCellRefMut};
964+ ///
965+ /// let c = GcCell::new(vec![1, 2, 3]);
966+ ///
967+ /// {
968+ /// let b1: GcCellRefMut<Vec<u32>> = c.borrow_mut();
969+ /// let mut b2: Result<GcCellRefMut<Vec<u32>, u32>, _> = GcCellRefMut::filter_map(b1, |v| v.get_mut(1));
970+ ///
971+ /// if let Ok(mut b2) = b2 {
972+ /// *b2 += 2;
973+ /// }
974+ /// }
975+ ///
976+ /// assert_eq!(*c.borrow(), vec![1, 4, 3]);
977+ /// ```
978+ #[ inline]
979+ pub fn filter_map < V , F > ( orig : Self , f : F ) -> Result < GcCellRefMut < ' a , T , V > , Self >
980+ where
981+ V : ?Sized ,
982+ F : FnOnce ( & mut U ) -> Option < & mut V > ,
983+ {
984+ let gc_cell = orig. gc_cell ;
985+
986+ // Use MaybeUninit to avoid calling the destructor of
987+ // GcCellRefMut (which would update the borrow flags) and to
988+ // avoid duplicating the mutable reference orig.value (which
989+ // would be UB).
990+ let orig = mem:: MaybeUninit :: new ( orig) ;
991+ let value = unsafe { ptr:: addr_of!( ( * orig. as_ptr( ) ) . value) . read ( ) } ;
992+
993+ match f ( value) {
994+ None => Err ( unsafe { orig. assume_init ( ) } ) ,
995+ Some ( value) => Ok ( GcCellRefMut { gc_cell, value } ) ,
996+ }
997+ }
949998}
950999
9511000impl < ' a , T : Trace + ?Sized , U : ?Sized > Deref for GcCellRefMut < ' a , T , U > {
0 commit comments