mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-19 11:12:43 +00:00
Rollup merge of #99386 - AngelicosPhosphoros:add_retain_test_maybeuninit, r=JohnTitor
Add tests that check `Vec::retain` predicate execution order. This behaviour is documented for `Vec::retain` which means that there is code that rely on that but there weren't tests about that.
This commit is contained in:
commit
33b5ce6433
@ -293,6 +293,22 @@ fn test_retain() {
|
||||
assert_eq!(vec, [2, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_retain_predicate_order() {
|
||||
for to_keep in [true, false] {
|
||||
let mut number_of_executions = 0;
|
||||
let mut vec = vec![1, 2, 3, 4];
|
||||
let mut next_expected = 1;
|
||||
vec.retain(|&x| {
|
||||
assert_eq!(next_expected, x);
|
||||
next_expected += 1;
|
||||
number_of_executions += 1;
|
||||
to_keep
|
||||
});
|
||||
assert_eq!(number_of_executions, 4);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_retain_pred_panic_with_hole() {
|
||||
let v = (0..5).map(Rc::new).collect::<Vec<_>>();
|
||||
@ -354,6 +370,35 @@ fn test_retain_drop_panic() {
|
||||
assert!(v.iter().all(|r| Rc::strong_count(r) == 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_retain_maybeuninits() {
|
||||
// This test aimed to be run under miri.
|
||||
use core::mem::MaybeUninit;
|
||||
let mut vec: Vec<_> = [1i32, 2, 3, 4].map(|v| MaybeUninit::new(vec![v])).into();
|
||||
vec.retain(|x| {
|
||||
// SAFETY: Retain must visit every element of Vec in original order and exactly once.
|
||||
// Our values is initialized at creation of Vec.
|
||||
let v = unsafe { x.assume_init_ref()[0] };
|
||||
if v & 1 == 0 {
|
||||
return true;
|
||||
}
|
||||
// SAFETY: Value is initialized.
|
||||
// Value wouldn't be dropped by `Vec::retain`
|
||||
// because `MaybeUninit` doesn't drop content.
|
||||
drop(unsafe { x.assume_init_read() });
|
||||
false
|
||||
});
|
||||
let vec: Vec<i32> = vec
|
||||
.into_iter()
|
||||
.map(|x| unsafe {
|
||||
// SAFETY: All values dropped in retain predicate must be removed by `Vec::retain`.
|
||||
// Remaining values are initialized.
|
||||
x.assume_init()[0]
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(vec, [2, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dedup() {
|
||||
fn case(a: Vec<i32>, b: Vec<i32>) {
|
||||
|
Loading…
Reference in New Issue
Block a user