about summary refs log tree commit diff
diff options
context:
space:
mode:
authorfee1-dead <ent3rm4n@gmail.com>2022-04-12 22:44:45 +1000
committerGitHub <noreply@github.com>2022-04-12 22:44:45 +1000
commit1d76dd9ee7fd33585f69d8ca799283724725430e (patch)
treed75bd12072cbf66ffeb705cb673b1bea69a8d4b2
parentcdbdf1ef2e4cca6dabc43a2d5101f283e18e2ce7 (diff)
parent2d5eda8fb0392f469e599a6ac3fb23461161dff6 (diff)
downloadrust-1d76dd9ee7fd33585f69d8ca799283724725430e.tar.gz
rust-1d76dd9ee7fd33585f69d8ca799283724725430e.zip
Rollup merge of #95947 - cuviper:default-box, r=dtolnay
`impl const Default for Box<[T]>` and `Box<str>`

The unstable `const_default_impls` (#87864) already include empty `Vec<T>` and `String`. Now we extend that concept to `Box<[T]>` and `Box<str>` as well.

This obviates a hack in `rustc_ast`'s `P::<[T]>::new`.
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/ptr.rs9
-rw-r--r--library/alloc/src/boxed.rs16
-rw-r--r--library/alloc/tests/const_fns.rs6
4 files changed, 21 insertions, 12 deletions
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 538bfc21290..a7c23dbb79c 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -9,6 +9,8 @@
     test(attr(deny(warnings)))
 )]
 #![feature(box_patterns)]
+#![feature(const_default_impls)]
+#![feature(const_trait_impl)]
 #![feature(crate_visibility_modifier)]
 #![feature(if_let_guard)]
 #![feature(label_break_value)]
diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs
index 70dbda82224..89a0857992e 100644
--- a/compiler/rustc_ast/src/ptr.rs
+++ b/compiler/rustc_ast/src/ptr.rs
@@ -128,14 +128,7 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
 
 impl<T> P<[T]> {
     pub const fn new() -> P<[T]> {
-        // HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>`
-        // (as trait methods, `default` in this case, can't be `const fn` yet).
-        P {
-            ptr: unsafe {
-                use std::ptr::NonNull;
-                std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>)
-            },
-        }
+        P { ptr: Box::default() }
     }
 
     #[inline(never)]
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index e6faf1df3a8..639e7f213ea 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1192,17 +1192,25 @@ impl<T: Default> Default for Box<T> {
 
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Default for Box<[T]> {
+#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
+impl<T> const Default for Box<[T]> {
     fn default() -> Self {
-        Box::<[T; 0]>::new([])
+        let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling();
+        Box(ptr, Global)
     }
 }
 
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "default_box_extra", since = "1.17.0")]
-impl Default for Box<str> {
+#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
+impl const Default for Box<str> {
     fn default() -> Self {
-        unsafe { from_boxed_utf8_unchecked(Default::default()) }
+        // SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`.
+        let ptr: Unique<str> = unsafe {
+            let bytes: Unique<[u8]> = Unique::<[u8; 0]>::dangling();
+            Unique::new_unchecked(bytes.as_ptr() as *mut str)
+        };
+        Box(ptr, Global)
     }
 }
 
diff --git a/library/alloc/tests/const_fns.rs b/library/alloc/tests/const_fns.rs
index f448b3eb7c3..49b837becbc 100644
--- a/library/alloc/tests/const_fns.rs
+++ b/library/alloc/tests/const_fns.rs
@@ -6,6 +6,9 @@ pub const MY_VEC2: Vec<usize> = Default::default();
 pub const MY_STRING: String = String::new();
 pub const MY_STRING2: String = Default::default();
 
+pub const MY_BOXED_SLICE: Box<[usize]> = Default::default();
+pub const MY_BOXED_STR: Box<str> = Default::default();
+
 use std::collections::{BTreeMap, BTreeSet};
 
 pub const MY_BTREEMAP: BTreeMap<usize, usize> = BTreeMap::new();
@@ -23,6 +26,9 @@ fn test_const() {
     assert_eq!(MY_VEC, MY_VEC2);
     assert_eq!(MY_STRING, MY_STRING2);
 
+    assert_eq!(MY_VEC, *MY_BOXED_SLICE);
+    assert_eq!(MY_STRING, *MY_BOXED_STR);
+
     assert_eq!(MAP_LEN, 0);
     assert_eq!(SET_LEN, 0);
     assert!(MAP_IS_EMPTY && SET_IS_EMPTY);