Use MaybeUninit
instead of writing directly into uninitialized Vec
.
This addresses a precondition error which is caught in newer stdlib.
This commit is contained in:
parent
1fcff8f4eb
commit
d94fd76d94
@ -10,7 +10,7 @@ use std::cmp::Eq;
|
||||
use std::collections::VecDeque;
|
||||
use std::hash::Hash;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use crate::base::{EdgeId, VertexId};
|
||||
use crate::Graph;
|
||||
@ -28,22 +28,16 @@ fn permute_compact<T>(data: &mut Vec<T>, f: impl Fn(usize) -> Option<usize>) {
|
||||
|
||||
// TODO: We should benchmark doing this in-place vs. via moving.
|
||||
let mut new_data: Vec<T> = Vec::with_capacity(data.len());
|
||||
// TODO: This relies on an implementation detail of Vec (namely, that
|
||||
// Vec::with_capacity gives us a block that we can read into with
|
||||
// get_unchecked_mut, even if the index we're accessing is beyond the length
|
||||
// of the Vec). This seems unlikely to change, but it may ultimately be more
|
||||
// future-proof to allocate a block of memory, do writes into it manually,
|
||||
// and pass it to Vec::from_raw_parts.
|
||||
let buffer: &mut [mem::MaybeUninit<T>] =
|
||||
unsafe { slice::from_raw_parts_mut(new_data.as_mut_ptr() as _, new_data.capacity()) };
|
||||
let compacted = data
|
||||
.drain(..)
|
||||
.enumerate()
|
||||
.filter_map(|(old_index, t)| f(old_index).map(|new_index| (new_index, t)));
|
||||
let mut retained_count = 0;
|
||||
{
|
||||
let compacted = data
|
||||
.drain(..)
|
||||
.enumerate()
|
||||
.filter_map(|(old_index, t)| f(old_index).map(|new_index| (new_index, t)));
|
||||
for (new_index, t) in compacted {
|
||||
unsafe { ptr::write(new_data.get_unchecked_mut(new_index), t) };
|
||||
retained_count += 1;
|
||||
}
|
||||
for (new_index, t) in compacted {
|
||||
buffer[new_index].write(t);
|
||||
retained_count += 1;
|
||||
}
|
||||
unsafe { new_data.set_len(retained_count) }; // TODO: Maybe do this after each swap?
|
||||
*data = new_data;
|
||||
|
Loading…
Reference in New Issue
Block a user