Skip to content

Commit 329c85d

Browse files
committed
implement Default using const generics
1 parent c724b67 commit 329c85d

File tree

2 files changed

+76
-23
lines changed

2 files changed

+76
-23
lines changed

src/libcore/array/mod.rs

+75-23
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,81 @@ where
387387
}
388388
}
389389

390+
/// A trait implemented by all arrays which are either empty or contain a type implementing `Default`.
391+
#[unstable(feature = "array_default_internals", reason = "implementation detail", issue = "none")]
392+
#[marker]
393+
pub trait ArrayDefault {}
394+
395+
#[unstable(feature = "array_default_internals", reason = "implementation detail", issue = "none")]
396+
impl<T> ArrayDefault for [T; 0] {}
397+
398+
#[unstable(feature = "array_default_internals", reason = "implementation detail", issue = "none")]
399+
impl<T: Default, const N: usize> ArrayDefault for [T; N] {}
400+
401+
trait DefaultHack {
402+
fn default_hack() -> Self;
403+
}
404+
405+
impl<T> DefaultHack for T {
406+
default fn default_hack() -> Self {
407+
unreachable!();
408+
}
409+
}
410+
411+
impl<T: Default> DefaultHack for T {
412+
#[inline(always)]
413+
fn default_hack() -> Self {
414+
Default::default()
415+
}
416+
}
417+
418+
#[stable(since = "1.4.0", feature = "array_default")]
419+
impl<T, const N: usize> Default for [T; N]
420+
where
421+
[T; N]: ArrayDefault + LengthAtMost32,
422+
{
423+
#[inline]
424+
fn default() -> [T; N] {
425+
use crate::mem::MaybeUninit;
426+
let mut data: MaybeUninit<[T; N]> = MaybeUninit::uninit();
427+
// Invariant: first `init` items are initialized
428+
struct Guard<T, const N: usize> {
429+
data: *mut T,
430+
init: usize,
431+
}
432+
433+
impl<T, const N: usize> Drop for Guard<T, N> {
434+
#[inline]
435+
fn drop(&mut self) {
436+
debug_assert!(self.init <= N);
437+
438+
let initialized_part = crate::ptr::slice_from_raw_parts_mut(self.data, self.init);
439+
// SAFETY: this raw slice will contain only initialized objects
440+
// that's why, it is allowed to drop it.
441+
unsafe {
442+
crate::ptr::drop_in_place(initialized_part);
443+
}
444+
}
445+
}
446+
447+
let mut w = Guard::<T, N> { data: data.as_mut_ptr() as *mut T, init: 0 };
448+
// SAFETY: in fact we go from &mut MaybeUninit<[T; N]> to &mut [MaybeUninit<T>; N].
449+
// it is always correct.
450+
let slots = unsafe { &mut *(data.as_mut_ptr() as *mut [MaybeUninit<T>; N]) };
451+
for slot in slots.iter_mut() {
452+
slot.write(T::default_hack());
453+
// now, when slot is filled with value, we can increment
454+
// `init`.
455+
w.init += 1;
456+
}
457+
458+
// Prevent double-read in callee and Wrapper::drop
459+
crate::mem::forget(w);
460+
// SAFETY: at this point whole array is initialized.
461+
unsafe { data.assume_init() }
462+
}
463+
}
464+
390465
/// Implemented for lengths where trait impls are allowed on arrays in core/std
391466
#[rustc_on_unimplemented(message = "arrays only have std trait implementations for lengths 0..=32")]
392467
#[unstable(
@@ -411,26 +486,3 @@ array_impls! {
411486
20 21 22 23 24 25 26 27 28 29
412487
30 31 32
413488
}
414-
415-
// The Default impls cannot be generated using the array_impls! macro because
416-
// they require array literals.
417-
418-
macro_rules! array_impl_default {
419-
{$n:expr, $t:ident $($ts:ident)*} => {
420-
#[stable(since = "1.4.0", feature = "array_default")]
421-
impl<T> Default for [T; $n] where T: Default {
422-
fn default() -> [T; $n] {
423-
[$t::default(), $($ts::default()),*]
424-
}
425-
}
426-
array_impl_default!{($n - 1), $($ts)*}
427-
};
428-
{$n:expr,} => {
429-
#[stable(since = "1.4.0", feature = "array_default")]
430-
impl<T> Default for [T; $n] {
431-
fn default() -> [T; $n] { [] }
432-
}
433-
};
434-
}
435-
436-
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}

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
#![feature(unwind_attributes)]
128128
#![cfg_attr(not(bootstrap), feature(variant_count))]
129129
#![feature(doc_alias)]
130+
#![feature(marker_trait_attr)]
130131
#![feature(mmx_target_feature)]
131132
#![feature(tbm_target_feature)]
132133
#![feature(sse4a_target_feature)]

0 commit comments

Comments
 (0)