Skip to content

Commit 3a5fe37

Browse files
committed
Add drop guard
1 parent 5b8e177 commit 3a5fe37

File tree

1 file changed

+27
-1
lines changed

1 file changed

+27
-1
lines changed

library/core/src/array/mod.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ macro_rules! array_impl_default {
365365

366366
array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
367367

368-
#[lang = "array"]
369368
#[cfg(not(bootstrap))]
369+
#[lang = "array"]
370370
impl<T, const N: usize> [T; N] {
371371
/// Returns an array of the same size as self, with `f` applied to each element.
372372
///
@@ -382,9 +382,35 @@ impl<T, const N: usize> [T; N] {
382382
F: FnMut(T) -> S,
383383
{
384384
use crate::mem::MaybeUninit;
385+
struct Guard<T, const N: usize> {
386+
dst: *mut T,
387+
curr_init: usize,
388+
}
389+
390+
impl<T, const N: usize> Guard<T, N> {
391+
fn new(dst: &mut [MaybeUninit<T>; N]) -> Self {
392+
Guard { dst: dst as *mut _ as *mut T, curr_init: 0 }
393+
}
394+
}
395+
396+
impl<T, const N: usize> Drop for Guard<T, N> {
397+
fn drop(&mut self) {
398+
debug_assert!(self.curr_init <= N);
399+
400+
let initialized_part =
401+
crate::ptr::slice_from_raw_parts_mut(self.dst, self.curr_init);
402+
// SAFETY: this raw slice will contain only initialized objects
403+
// that's why, it is allowed to drop it.
404+
unsafe {
405+
crate::ptr::drop_in_place(initialized_part);
406+
}
407+
}
408+
}
385409
let dst = MaybeUninit::uninit_array::<N>();
410+
let mut guard = Guard::new(&mut dst);
386411
for (i, e) in self.into_iter().enumerate() {
387412
dst[i] = MaybeUninit::new(f(e));
413+
guard.curr_init += 1;
388414
}
389415
// FIXME convert to crate::mem::transmute when works with generics
390416
// unsafe { crate::mem::transmute::<[MaybeUninit<S>; N], [S; N]>(dst) }

0 commit comments

Comments
 (0)