Skip to content

Commit ff12204

Browse files
committed
Default for arrays via const generics
1 parent 790d19c commit ff12204

File tree

3 files changed

+53
-19
lines changed

3 files changed

+53
-19
lines changed

library/core/src/array/mod.rs

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -353,28 +353,60 @@ impl<T: Ord, const N: usize> Ord for [T; N] {
353353
}
354354
}
355355

356-
// The Default impls cannot be generated using the array_impls! macro because
357-
// they require array literals.
358-
359-
macro_rules! array_impl_default {
360-
{$n:expr, $t:ident $($ts:ident)*} => {
361-
#[stable(since = "1.4.0", feature = "array_default")]
362-
impl<T> Default for [T; $n] where T: Default {
363-
fn default() -> [T; $n] {
364-
[$t::default(), $($ts::default()),*]
365-
}
356+
/// This module implements `Default` for arrays.
357+
mod default_impls {
358+
// A trait implemented by all arrays which are either empty or contain a type implementing `Default`.
359+
#[unstable(
360+
feature = "array_default_internals",
361+
reason = "implementation detail",
362+
issue = "none"
363+
)]
364+
#[marker]
365+
pub trait ArrayDefault {}
366+
367+
#[unstable(
368+
feature = "array_default_internals",
369+
reason = "implementation detail",
370+
issue = "none"
371+
)]
372+
impl<T> ArrayDefault for [T; 0] {}
373+
374+
#[unstable(
375+
feature = "array_default_internals",
376+
reason = "implementation detail",
377+
issue = "none"
378+
)]
379+
impl<T: Default, const N: usize> ArrayDefault for [T; N] {}
380+
381+
trait DefaultHack {
382+
fn default_hack() -> Self;
383+
}
384+
385+
impl<T> DefaultHack for T {
386+
default fn default_hack() -> Self {
387+
unreachable!();
366388
}
367-
array_impl_default!{($n - 1), $($ts)*}
368-
};
369-
{$n:expr,} => {
370-
#[stable(since = "1.4.0", feature = "array_default")]
371-
impl<T> Default for [T; $n] {
372-
fn default() -> [T; $n] { [] }
389+
}
390+
391+
impl<T: Default> DefaultHack for T {
392+
fn default_hack() -> Self {
393+
Default::default()
373394
}
374-
};
395+
}
396+
#[stable(since = "1.4.0", feature = "array_default")]
397+
impl<T, const N: usize> Default for [T; N]
398+
where
399+
[T; N]: ArrayDefault,
400+
{
401+
fn default() -> [T; N] {
402+
assert_eq!(std::mem::size_of::<[(); N]>(), 0);
403+
// SAFETY: it is always valid to use `ceroed` for zero-sized value.
404+
let arr: [(); N] = unsafe { std::mem::zeroed() };
405+
arr.map(DefaultHack::default_hack)
406+
}
407+
}
375408
}
376409

377-
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}
378410

379411
#[lang = "array"]
380412
impl<T, const N: usize> [T; N] {

library/core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#![allow(explicit_outlives_requirements)]
6565
#![allow(incomplete_features)]
6666
#![feature(allow_internal_unstable)]
67+
#![feature(array_default_internals)]
6768
#![feature(arbitrary_self_types)]
6869
#![feature(asm)]
6970
#![feature(cfg_target_has_atomic)]
@@ -111,6 +112,7 @@
111112
#![feature(lang_items)]
112113
#![feature(link_llvm_intrinsics)]
113114
#![feature(llvm_asm)]
115+
#![feature(marker_trait_attr)]
114116
#![feature(negative_impls)]
115117
#![feature(never_type)]
116118
#![feature(nll)]

library/core/tests/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
288288
}
289289
}
290290

291-
let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
291+
let res = std::panic::catch_unwind(|| <[Bomb; 35]>::default());
292292
let panic_msg = match res {
293293
Ok(_) => unreachable!(),
294294
Err(p) => p.downcast::<&'static str>().unwrap(),

0 commit comments

Comments
 (0)