Skip to content

Commit 85a9c74

Browse files
Add tests that check Vec::retain predicate execution order.
1 parent ada8c80 commit 85a9c74

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

library/alloc/tests/vec.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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]
296312
fn 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]
357402
fn test_dedup() {
358403
fn case(a: Vec<i32>, b: Vec<i32>) {

0 commit comments

Comments
 (0)