@@ -292,6 +292,22 @@ fn test_retain() {
292
292
assert_eq ! ( vec, [ 2 , 4 ] ) ;
293
293
}
294
294
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
+
295
311
#[ test]
296
312
fn test_retain_pred_panic_with_hole ( ) {
297
313
let v = ( 0 ..5 ) . map ( Rc :: new) . collect :: < Vec < _ > > ( ) ;
@@ -353,6 +369,35 @@ fn test_retain_drop_panic() {
353
369
assert ! ( v. iter( ) . all( |r| Rc :: strong_count( r) == 1 ) ) ;
354
370
}
355
371
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
+
356
401
#[ test]
357
402
fn test_dedup ( ) {
358
403
fn case ( a : Vec < i32 > , b : Vec < i32 > ) {
0 commit comments