diff options
| author | fee1-dead <ent3rm4n@gmail.com> | 2022-04-12 22:44:45 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-12 22:44:45 +1000 |
| commit | 1d76dd9ee7fd33585f69d8ca799283724725430e (patch) | |
| tree | d75bd12072cbf66ffeb705cb673b1bea69a8d4b2 | |
| parent | cdbdf1ef2e4cca6dabc43a2d5101f283e18e2ce7 (diff) | |
| parent | 2d5eda8fb0392f469e599a6ac3fb23461161dff6 (diff) | |
| download | rust-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.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/ptr.rs | 9 | ||||
| -rw-r--r-- | library/alloc/src/boxed.rs | 16 | ||||
| -rw-r--r-- | library/alloc/tests/const_fns.rs | 6 |
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); |
