diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 5f20729568352..3e791416820ef 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1688,7 +1688,7 @@ impl Default for Box { /// Creates a `Box`, with the `Default` value for T. #[inline] fn default() -> Self { - Box::new(T::default()) + Box::write(Box::new_uninit(), T::default()) } } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 50bf385d671e3..fa4bb784a3212 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -104,6 +104,7 @@ #![feature(async_closure)] #![feature(async_fn_traits)] #![feature(async_iterator)] +#![feature(box_uninit_write)] #![feature(clone_to_uninit)] #![feature(coerce_unsized)] #![feature(const_align_of_val)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4632f995b82e3..acbc325a51415 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3447,7 +3447,13 @@ impl Default for Arc { /// assert_eq!(*x, 0); /// ``` fn default() -> Arc { - Arc::new(Default::default()) + let x = Box::into_raw(Box::write(Box::new_uninit(), ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: T::default(), + })); + // SAFETY: `Box::into_raw` consumes the `Box` and never returns null + unsafe { Self::from_inner(NonNull::new_unchecked(x)) } } } diff --git a/tests/codegen/placement-new.rs b/tests/codegen/placement-new.rs new file mode 100644 index 0000000000000..edb25df5eb4dc --- /dev/null +++ b/tests/codegen/placement-new.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -O +#![crate_type = "lib"] + +// Test to check that types with "complex" destructors, but trivial `Default` impls +// are constructed directly into the allocation in `Box::default` and `Arc::default`. + +use std::sync::Arc; + +// CHECK-LABEL: @box_default_inplace +#[no_mangle] +pub fn box_default_inplace() -> Box<(String, String)> { + // CHECK-NOT: alloca + // CHECK: [[BOX:%.*]] = {{.*}}call {{.*}}__rust_alloc( + // CHECK-NOT: call void @llvm.memcpy + // CHECK: ret ptr [[BOX]] + Box::default() +} + +// CHECK-LABEL: @arc_default_inplace +#[no_mangle] +pub fn arc_default_inplace() -> Arc<(String, String)> { + // CHECK-NOT: alloca + // CHECK: [[ARC:%.*]] = {{.*}}call {{.*}}__rust_alloc( + // CHECK-NOT: call void @llvm.memcpy + // CHECK: ret ptr [[ARC]] + Arc::default() +}