@@ -292,6 +292,22 @@ fn test_retain() {
292292 assert_eq ! ( vec, [ 2 , 4 ] ) ;
293293}
294294
295+ #[ test]
296+ fn test_retain_predicate_order ( ) {
297+ for to_keep in [ true , false ] {
298+ let mut number_of_executions = 0 ;
299+ let mut vec = vec ! [ 1 , 2 , 3 , 4 ] ;
300+ let mut next_expected = 1 ;
301+ vec. retain ( |& x| {
302+ assert_eq ! ( next_expected, x) ;
303+ next_expected += 1 ;
304+ number_of_executions += 1 ;
305+ to_keep
306+ } ) ;
307+ assert_eq ! ( number_of_executions, 4 ) ;
308+ }
309+ }
310+
295311#[ test]
296312fn test_retain_pred_panic_with_hole ( ) {
297313 let v = ( 0 ..5 ) . map ( Rc :: new) . collect :: < Vec < _ > > ( ) ;
@@ -353,6 +369,35 @@ fn test_retain_drop_panic() {
353369 assert ! ( v. iter( ) . all( |r| Rc :: strong_count( r) == 1 ) ) ;
354370}
355371
372+ #[ test]
373+ fn test_retain_maybeuninits ( ) {
374+ // This test aimed to be run under miri.
375+ use core:: mem:: MaybeUninit ;
376+ let mut vec: Vec < _ > = [ 1i32 , 2 , 3 , 4 ] . map ( |v| MaybeUninit :: new ( vec ! [ v] ) ) . into ( ) ;
377+ vec. retain ( |x| {
378+ // SAFETY: Retain must visit every element of Vec in original order and exactly once.
379+ // Our values is initialized at creation of Vec.
380+ let v = unsafe { x. assume_init_ref ( ) [ 0 ] } ;
381+ if v & 1 == 0 {
382+ return true ;
383+ }
384+ // SAFETY: Value is initialized.
385+ // Value wouldn't be dropped by `Vec::retain`
386+ // because `MaybeUninit` doesn't drop content.
387+ drop ( unsafe { x. assume_init_read ( ) } ) ;
388+ false
389+ } ) ;
390+ let vec: Vec < i32 > = vec
391+ . into_iter ( )
392+ . map ( |x| unsafe {
393+ // SAFETY: All values dropped in retain predicate must be removed by `Vec::retain`.
394+ // Remaining values are initialized.
395+ x. assume_init ( ) [ 0 ]
396+ } )
397+ . collect ( ) ;
398+ assert_eq ! ( vec, [ 2 , 4 ] ) ;
399+ }
400+
356401#[ test]
357402fn test_dedup ( ) {
358403 fn case ( a : Vec < i32 > , b : Vec < i32 > ) {
0 commit comments