Skip to content

Commit

Permalink
Rollup merge of rust-lang#95947 - cuviper:default-box, r=dtolnay
Browse files Browse the repository at this point in the history
`impl const Default for Box<[T]>` and `Box<str>`

The unstable `const_default_impls` (rust-lang#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`.
  • Loading branch information
fee1-dead committed Apr 12, 2022
2 parents cdbdf1e + 2d5eda8 commit 1d76dd9
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 12 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_ast/src/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
16 changes: 12 additions & 4 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
6 changes: 6 additions & 0 deletions library/alloc/tests/const_fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
Expand Down

0 comments on commit 1d76dd9

Please sign in to comment.