@@ -1319,6 +1319,127 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
13191319 self . drain_filter ( |x| !f ( x) ) ;
13201320 }
13211321
1322+ /// Retains only the elements specified by the predicate, passing a mutable reference to it.
1323+ ///
1324+ /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`.
1325+ /// This method operates in place, visiting each element exactly once in the
1326+ /// original order, and preserves the order of the retained elements.
1327+ ///
1328+ /// # Examples
1329+ ///
1330+ /// ```
1331+ /// let mut vec = vec![1, 2, 3, 4];
1332+ /// vec.retain_mut(|x| if *x <= 3 {
1333+ /// *x += 1;
1334+ /// true
1335+ /// } else {
1336+ /// false
1337+ /// });
1338+ /// assert_eq!(vec, [2, 3, 4]);
1339+ /// ```
1340+ // The implementation is based on the [`std::vec::Vec::retain_mut`].
1341+ //
1342+ // Allowing the following clippy rules just to make the code same as the original implementation.
1343+ #[ expect( clippy:: items_after_statements, clippy:: redundant_else) ]
1344+ pub fn retain_mut < F > ( & mut self , mut f : F )
1345+ where
1346+ F : FnMut ( & mut T ) -> bool ,
1347+ {
1348+ let original_len = self . len ( ) ;
1349+
1350+ if original_len == 0 {
1351+ // Empty case: explicit return allows better optimization, vs letting compiler infer it
1352+ return ;
1353+ }
1354+
1355+ // Avoid double drop if the drop guard is not executed,
1356+ // since we may make some holes during the process.
1357+ unsafe { self . set_len ( 0 ) } ;
1358+
1359+ // Vec: [Kept, Kept, Hole, Hole, Hole, Hole, Unchecked, Unchecked]
1360+ // |<- processed len ->| ^- next to check
1361+ // |<- deleted cnt ->|
1362+ // |<- original_len ->|
1363+ // Kept: Elements which predicate returns true on.
1364+ // Hole: Moved or dropped element slot.
1365+ // Unchecked: Unchecked valid elements.
1366+ //
1367+ // This drop guard will be invoked when predicate or `drop` of element panicked.
1368+ // It shifts unchecked elements to cover holes and `set_len` to the correct length.
1369+ // In cases when predicate and `drop` never panick, it will be optimized out.
1370+ struct BackshiftOnDrop < ' bump , ' a , T > {
1371+ v : & ' a mut Vec < ' bump , T > ,
1372+ processed_len : usize ,
1373+ deleted_cnt : usize ,
1374+ original_len : usize ,
1375+ }
1376+
1377+ impl < T > Drop for BackshiftOnDrop < ' _ , ' _ , T > {
1378+ fn drop ( & mut self ) {
1379+ if self . deleted_cnt > 0 {
1380+ // SAFETY: Trailing unchecked items must be valid since we never touch them.
1381+ unsafe {
1382+ ptr:: copy (
1383+ self . v . as_ptr ( ) . add ( self . processed_len ) ,
1384+ self . v . as_mut_ptr ( ) . add ( self . processed_len - self . deleted_cnt ) ,
1385+ self . original_len - self . processed_len ,
1386+ ) ;
1387+ }
1388+ }
1389+ // SAFETY: After filling holes, all items are in contiguous memory.
1390+ unsafe {
1391+ self . v . set_len ( self . original_len - self . deleted_cnt ) ;
1392+ }
1393+ }
1394+ }
1395+
1396+ let mut g = BackshiftOnDrop { v : self , processed_len : 0 , deleted_cnt : 0 , original_len } ;
1397+
1398+ fn process_loop < F , T , const DELETED : bool > (
1399+ original_len : usize ,
1400+ f : & mut F ,
1401+ g : & mut BackshiftOnDrop < ' _ , ' _ , T > ,
1402+ ) where
1403+ F : FnMut ( & mut T ) -> bool ,
1404+ {
1405+ while g. processed_len != original_len {
1406+ // SAFETY: Unchecked element must be valid.
1407+ let cur = unsafe { & mut * g. v . as_mut_ptr ( ) . add ( g. processed_len ) } ;
1408+ if !f ( cur) {
1409+ // Advance early to avoid double drop if `drop_in_place` panicked.
1410+ g. processed_len += 1 ;
1411+ g. deleted_cnt += 1 ;
1412+ // SAFETY: We never touch this element again after dropped.
1413+ unsafe { ptr:: drop_in_place ( cur) } ;
1414+ // We already advanced the counter.
1415+ if DELETED {
1416+ continue ;
1417+ } else {
1418+ break ;
1419+ }
1420+ }
1421+ if DELETED {
1422+ // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element.
1423+ // We use copy for move, and never touch this element again.
1424+ unsafe {
1425+ let hole_slot = g. v . as_mut_ptr ( ) . add ( g. processed_len - g. deleted_cnt ) ;
1426+ ptr:: copy_nonoverlapping ( cur, hole_slot, 1 ) ;
1427+ }
1428+ }
1429+ g. processed_len += 1 ;
1430+ }
1431+ }
1432+
1433+ // Stage 1: Nothing was deleted.
1434+ process_loop :: < F , T , false > ( original_len, & mut f, & mut g) ;
1435+
1436+ // Stage 2: Some elements were deleted.
1437+ process_loop :: < F , T , true > ( original_len, & mut f, & mut g) ;
1438+
1439+ // All item are processed. This can be optimized to `set_len` by LLVM.
1440+ drop ( g) ;
1441+ }
1442+
13221443 /// Creates an iterator that removes the elements in the vector
13231444 /// for which the predicate returns `true` and yields the removed items.
13241445 ///
@@ -2070,7 +2191,7 @@ where
20702191 }
20712192}
20722193
2073- impl < ' bump , T : ' bump > ops:: Deref for Vec < ' bump , T > {
2194+ impl < T > ops:: Deref for Vec < ' _ , T > {
20742195 type Target = [ T ] ;
20752196
20762197 fn deref ( & self ) -> & [ T ] {
@@ -2082,7 +2203,7 @@ impl<'bump, T: 'bump> ops::Deref for Vec<'bump, T> {
20822203 }
20832204}
20842205
2085- impl < ' bump , T : ' bump > ops:: DerefMut for Vec < ' bump , T > {
2206+ impl < T > ops:: DerefMut for Vec < ' _ , T > {
20862207 fn deref_mut ( & mut self ) -> & mut [ T ] {
20872208 unsafe {
20882209 let ptr = self . buf . ptr ( ) ;
0 commit comments