From b5afa6807b868bc8bb2e6f972629769b150ffd41 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 14 Aug 2021 16:35:12 +0000 Subject: [PATCH 1/2] Constified `Default` implementations The libs-api team agrees to allow const_trait_impl to appear in the standard library as long as stable code cannot be broken (they are properly gated) this means if the compiler teams thinks it's okay, then it's okay. My priority on constifying would be: 1. Non-generic impls (e.g. Default) or generic impls with no bounds 2. Generic functions with bounds (that use const impls) 3. Generic impls with bounds 4. Impls for traits with associated types For people opening constification PRs: please cc me and/or oli-obk. --- library/alloc/src/lib.rs | 1 + library/alloc/src/string.rs | 3 ++- library/alloc/src/vec/mod.rs | 3 ++- library/alloc/tests/const_fns.rs | 26 +++++++++++++------------- library/alloc/tests/lib.rs | 1 + library/core/src/array/mod.rs | 3 ++- library/core/src/default.rs | 3 ++- library/core/src/hash/mod.rs | 3 ++- library/core/src/iter/sources/empty.rs | 3 ++- library/core/src/lib.rs | 1 + library/core/src/marker.rs | 3 ++- library/core/src/option.rs | 3 ++- library/core/src/slice/mod.rs | 6 ++++-- library/core/src/str/mod.rs | 3 ++- library/core/src/sync/atomic.rs | 9 ++++++--- library/std/src/lazy.rs | 3 ++- library/std/src/lib.rs | 1 + 17 files changed, 47 insertions(+), 28 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index d2ececaa9759f..1a387f291ccf4 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -95,6 +95,7 @@ #![feature(const_fn_trait_bound)] #![feature(cow_is_borrowed)] #![feature(const_cow_is_borrowed)] +#![feature(const_trait_impl)] #![feature(destructuring_assignment)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 9aefd882af4e2..6568d9f9907b9 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2105,7 +2105,8 @@ impl_eq! { Cow<'a, str>, &'b str } impl_eq! { Cow<'a, str>, String } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for String { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for String { /// Creates an empty `String`. #[inline] fn default() -> String { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 933361d812cb0..87a0d37181562 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2758,7 +2758,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for Vec { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for Vec { /// Creates an empty `Vec`. fn default() -> Vec { Vec::new() diff --git a/library/alloc/tests/const_fns.rs b/library/alloc/tests/const_fns.rs index b6ef3eee291fb..da58ae92e1124 100644 --- a/library/alloc/tests/const_fns.rs +++ b/library/alloc/tests/const_fns.rs @@ -1,16 +1,8 @@ -// Test several functions can be used for constants -// 1. Vec::new() -// 2. String::new() -// 3. BTreeMap::new() -// 4. BTreeSet::new() +// Test const functions in the library -#[allow(dead_code)] -pub const MY_VEC: Vec = Vec::new(); - -#[allow(dead_code)] -pub const MY_STRING: String = String::new(); +use core::cmp::Ordering; -// FIXME(fee1-dead) remove this struct once we put `K: ?const Ord` on BTreeMap::new. +// FIXME remove this struct once we put `K: ?const Ord` on BTreeMap::new. #[derive(PartialEq, Eq, PartialOrd)] pub struct MyType; @@ -32,7 +24,12 @@ impl const Ord for MyType { } } -use core::cmp::Ordering; +pub const MY_VEC: Vec = Vec::new(); +pub const MY_VEC2: Vec = Default::default(); + +pub const MY_STRING: String = String::new(); +pub const MY_STRING2: String = Default::default(); + use std::collections::{BTreeMap, BTreeSet}; pub const MY_BTREEMAP: BTreeMap = BTreeMap::new(); @@ -47,7 +44,10 @@ pub const SET_IS_EMPTY: bool = SET.is_empty(); #[test] fn test_const() { + assert_eq!(MY_VEC, MY_VEC2); + assert_eq!(MY_STRING, MY_STRING2); + assert_eq!(MAP_LEN, 0); assert_eq!(SET_LEN, 0); - assert!(MAP_IS_EMPTY && SET_IS_EMPTY) + assert!(MAP_IS_EMPTY && SET_IS_EMPTY); } diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 7284c05d5ff16..5767108d423c6 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -24,6 +24,7 @@ #![feature(vec_spare_capacity)] #![feature(string_remove_matches)] #![feature(const_btree_new)] +#![feature(const_default_impls)] #![feature(const_trait_impl)] use std::collections::hash_map::DefaultHasher; diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 3bc9f71375cb8..3c638e655dc91 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -280,7 +280,8 @@ macro_rules! array_impl_default { }; {$n:expr,} => { #[stable(since = "1.4.0", feature = "array_default")] - impl Default for [T; $n] { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl const Default for [T; $n] { fn default() -> [T; $n] { [] } } }; diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 6400a9b859567..0ee8cd59ba4ff 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -171,7 +171,8 @@ pub macro Default($item:item) { macro_rules! default_impl { ($t:ty, $v:expr, $doc:tt) => { #[stable(feature = "rust1", since = "1.0.0")] - impl Default for $t { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl const Default for $t { #[inline] #[doc = $doc] fn default() -> $t { diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 9dbefe0822e36..510e233b43110 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -599,7 +599,8 @@ impl Clone for BuildHasherDefault { } #[stable(since = "1.7.0", feature = "build_hasher")] -impl Default for BuildHasherDefault { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for BuildHasherDefault { fn default() -> BuildHasherDefault { BuildHasherDefault(marker::PhantomData) } diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs index 919c564f2872a..a7d4646f5c597 100644 --- a/library/core/src/iter/sources/empty.rs +++ b/library/core/src/iter/sources/empty.rs @@ -85,7 +85,8 @@ impl Clone for Empty { // not #[derive] because that adds a Default bound on T, // which isn't necessary. #[stable(feature = "iter_empty", since = "1.2.0")] -impl Default for Empty { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for Empty { fn default() -> Empty { Empty(marker::PhantomData) } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 37c3f8d4c16ab..4ab7cc24a0d42 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -103,6 +103,7 @@ #![feature(const_type_id)] #![feature(const_type_name)] #![feature(const_unreachable_unchecked)] +#![feature(const_default_impls)] #![feature(duration_consts_2)] #![feature(ptr_metadata)] #![feature(slice_ptr_get)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index fb957348bebd3..333f81ce4cfc4 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -528,7 +528,8 @@ macro_rules! impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl Default for $t { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl const Default for $t { fn default() -> Self { Self } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 3f9f04606b36a..78f5954532ff0 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1642,7 +1642,8 @@ impl Clone for Option { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for Option { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for Option { /// Returns [`None`][Option::None]. /// /// # Examples diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 51227d5411549..361a9b03aebc7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3501,7 +3501,8 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for &[T] { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for &[T] { /// Creates an empty slice. fn default() -> Self { &[] @@ -3509,7 +3510,8 @@ impl Default for &[T] { } #[stable(feature = "mut_slice_default", since = "1.5.0")] -impl Default for &mut [T] { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for &mut [T] { /// Creates a mutable empty slice. fn default() -> Self { &mut [] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index d4e30e65ef85f..947afbdc68dfb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2442,7 +2442,8 @@ impl AsRef<[u8]> for str { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for &str { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for &str { /// Creates an empty str #[inline] fn default() -> Self { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index d908b6ecda352..d9de37e9c5197 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -138,7 +138,8 @@ pub struct AtomicBool { #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "rust1", since = "1.0.0")] -impl Default for AtomicBool { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for AtomicBool { /// Creates an `AtomicBool` initialized to `false`. #[inline] fn default() -> Self { @@ -168,7 +169,8 @@ pub struct AtomicPtr { #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] -impl Default for AtomicPtr { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for AtomicPtr { /// Creates a null `AtomicPtr`. fn default() -> AtomicPtr { AtomicPtr::new(crate::ptr::null_mut()) @@ -1351,7 +1353,8 @@ macro_rules! atomic_int { pub const $atomic_init: $atomic_type = $atomic_type::new(0); #[$stable] - impl Default for $atomic_type { + #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] + impl const Default for $atomic_type { #[inline] fn default() -> Self { Self::new(Default::default()) diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index 132733a052510..5afdb799f0c74 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -86,7 +86,8 @@ impl RefUnwindSafe for SyncOnceCell {} impl UnwindSafe for SyncOnceCell {} #[unstable(feature = "once_cell", issue = "74465")] -impl Default for SyncOnceCell { +#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] +impl const Default for SyncOnceCell { /// Creates a new empty cell. /// /// # Example diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 43db3f910224c..5e91a0cdbd6b5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -255,6 +255,7 @@ #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] #![feature(const_socketaddr)] +#![feature(const_trait_impl)] #![feature(container_error_extra)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] From 6bd2ecba726f06587d7d60ffca5605841ac39091 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 16 Aug 2021 15:55:35 +0000 Subject: [PATCH 2/2] Add ui test --- .../std-impl-gate.rs | 21 +++++++++++++++++++ .../std-impl-gate.stock.stderr | 9 ++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs new file mode 100644 index 0000000000000..c6975da7121f9 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.rs @@ -0,0 +1,21 @@ +// This tests feature gates for const impls in the standard library. + +// revisions: stock gated +//[gated] run-pass + +#![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] + +fn non_const_context() -> Vec { + Default::default() +} + +const fn const_context() -> Vec { + Default::default() + //[stock]~^ ERROR calls in constant functions are limited +} + +fn main() { + const VAL: Vec = const_context(); + + assert_eq!(VAL, non_const_context()); +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr new file mode 100644 index 0000000000000..55a0daaaec7bd --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/std-impl-gate.stock.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/std-impl-gate.rs:13:5 + | +LL | Default::default() + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`.