diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 966272ca11549..026b22d38609e 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -353,29 +353,57 @@ impl Ord for [T; N] { } } -// The Default impls cannot be generated using the array_impls! macro because -// they require array literals. - -macro_rules! array_impl_default { - {$n:expr, $t:ident $($ts:ident)*} => { - #[stable(since = "1.4.0", feature = "array_default")] - impl Default for [T; $n] where T: Default { - fn default() -> [T; $n] { - [$t::default(), $($ts::default()),*] - } +/// This module implements `Default` for arrays. +mod default_impls { + // A trait implemented by all arrays which are either empty or contain a type implementing `Default`. + #[unstable( + feature = "array_default_internals", + reason = "implementation detail", + issue = "none" + )] + #[marker] + pub trait ArrayDefault {} + + #[unstable( + feature = "array_default_internals", + reason = "implementation detail", + issue = "none" + )] + impl ArrayDefault for [T; 0] {} + + #[unstable( + feature = "array_default_internals", + reason = "implementation detail", + issue = "none" + )] + impl ArrayDefault for [T; N] {} + + trait DefaultHack { + fn default_hack() -> Self; + } + + impl DefaultHack for T { + default fn default_hack() -> Self { + unreachable!(); } - array_impl_default!{($n - 1), $($ts)*} - }; - {$n:expr,} => { - #[stable(since = "1.4.0", feature = "array_default")] - impl Default for [T; $n] { - fn default() -> [T; $n] { [] } + } + + impl DefaultHack for T { + fn default_hack() -> Self { + Default::default() } - }; + } + #[stable(since = "1.4.0", feature = "array_default")] + impl Default for [T; N] + where + [T; N]: ArrayDefault, + { + fn default() -> [T; N] { + [(); N].map(|_unit| DefaultHack::default_hack()) + } + } } -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} - #[lang = "array"] impl [T; N] { /// Returns an array of the same size as `self`, with function `f` applied to each element diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 9a8d65cd4e06b..9240c9764996a 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -81,6 +81,8 @@ /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +// specialization is used in array impls +#[rustc_specialization_trait] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index c9a80b5bc7722..94b628abb169f 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -64,6 +64,7 @@ #![allow(explicit_outlives_requirements)] #![allow(incomplete_features)] #![feature(allow_internal_unstable)] +#![cfg_attr(not(bootstrap), feature(array_default_internals))] #![feature(arbitrary_self_types)] #![feature(asm)] #![feature(cfg_target_has_atomic)] @@ -111,6 +112,7 @@ #![feature(lang_items)] #![feature(link_llvm_intrinsics)] #![feature(llvm_asm)] +#![feature(marker_trait_attr)] #![feature(negative_impls)] #![feature(never_type)] #![feature(nll)] diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 89c2a969c28bb..31f385a95b281 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -288,7 +288,7 @@ fn array_default_impl_avoids_leaks_on_panic() { } } - let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default()); + let res = std::panic::catch_unwind(|| <[Bomb; 35]>::default()); let panic_msg = match res { Ok(_) => unreachable!(), Err(p) => p.downcast::<&'static str>().unwrap(),