Skip to content

Commit 1d76dd9

Browse files
authored
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`.
2 parents cdbdf1e + 2d5eda8 commit 1d76dd9

File tree

4 files changed

+21
-12
lines changed

4 files changed

+21
-12
lines changed

compiler/rustc_ast/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
test(attr(deny(warnings)))
1010
)]
1111
#![feature(box_patterns)]
12+
#![feature(const_default_impls)]
13+
#![feature(const_trait_impl)]
1214
#![feature(crate_visibility_modifier)]
1315
#![feature(if_let_guard)]
1416
#![feature(label_break_value)]

compiler/rustc_ast/src/ptr.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,7 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
128128

129129
impl<T> P<[T]> {
130130
pub const fn new() -> P<[T]> {
131-
// HACK(eddyb) bypass the lack of a `const fn` to create an empty `Box<[T]>`
132-
// (as trait methods, `default` in this case, can't be `const fn` yet).
133-
P {
134-
ptr: unsafe {
135-
use std::ptr::NonNull;
136-
std::mem::transmute(NonNull::<[T; 0]>::dangling() as NonNull<[T]>)
137-
},
138-
}
131+
P { ptr: Box::default() }
139132
}
140133

141134
#[inline(never)]

library/alloc/src/boxed.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1192,17 +1192,25 @@ impl<T: Default> Default for Box<T> {
11921192

11931193
#[cfg(not(no_global_oom_handling))]
11941194
#[stable(feature = "rust1", since = "1.0.0")]
1195-
impl<T> Default for Box<[T]> {
1195+
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
1196+
impl<T> const Default for Box<[T]> {
11961197
fn default() -> Self {
1197-
Box::<[T; 0]>::new([])
1198+
let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling();
1199+
Box(ptr, Global)
11981200
}
11991201
}
12001202

12011203
#[cfg(not(no_global_oom_handling))]
12021204
#[stable(feature = "default_box_extra", since = "1.17.0")]
1203-
impl Default for Box<str> {
1205+
#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
1206+
impl const Default for Box<str> {
12041207
fn default() -> Self {
1205-
unsafe { from_boxed_utf8_unchecked(Default::default()) }
1208+
// SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`.
1209+
let ptr: Unique<str> = unsafe {
1210+
let bytes: Unique<[u8]> = Unique::<[u8; 0]>::dangling();
1211+
Unique::new_unchecked(bytes.as_ptr() as *mut str)
1212+
};
1213+
Box(ptr, Global)
12061214
}
12071215
}
12081216

library/alloc/tests/const_fns.rs

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ pub const MY_VEC2: Vec<usize> = Default::default();
66
pub const MY_STRING: String = String::new();
77
pub const MY_STRING2: String = Default::default();
88

9+
pub const MY_BOXED_SLICE: Box<[usize]> = Default::default();
10+
pub const MY_BOXED_STR: Box<str> = Default::default();
11+
912
use std::collections::{BTreeMap, BTreeSet};
1013

1114
pub const MY_BTREEMAP: BTreeMap<usize, usize> = BTreeMap::new();
@@ -23,6 +26,9 @@ fn test_const() {
2326
assert_eq!(MY_VEC, MY_VEC2);
2427
assert_eq!(MY_STRING, MY_STRING2);
2528

29+
assert_eq!(MY_VEC, *MY_BOXED_SLICE);
30+
assert_eq!(MY_STRING, *MY_BOXED_STR);
31+
2632
assert_eq!(MAP_LEN, 0);
2733
assert_eq!(SET_LEN, 0);
2834
assert!(MAP_IS_EMPTY && SET_IS_EMPTY);

0 commit comments

Comments
 (0)