about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/sync.rs8
-rw-r--r--tests/codegen/placement-new.rs27
4 files changed, 36 insertions, 2 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 5f207295683..3e791416820 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1688,7 +1688,7 @@ impl<T: Default> Default for Box<T> {
     /// Creates a `Box<T>`, 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 50bf385d671..fa4bb784a32 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 4632f995b82..acbc325a514 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -3447,7 +3447,13 @@ impl<T: Default> Default for Arc<T> {
     /// assert_eq!(*x, 0);
     /// ```
     fn default() -> Arc<T> {
-        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 00000000000..edb25df5eb4
--- /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()
+}