From dd0620b86721ae8cae86736443acd3f72ba6fc32 Mon Sep 17 00:00:00 2001 From: Joshua Wong Date: Wed, 9 Oct 2024 14:24:05 -0400 Subject: [PATCH] allocate before calling T::default in >::default() The `Box` impl currently calls `T::default()` before allocating the `Box`. Most `Default` impls are trivial, which should in theory allow LLVM to construct `T: Default` directly in the `Box` allocation when calling `>::default()`. However, the allocation may fail, which necessitates calling `T's` destructor if it has one. If the destructor is non-trivial, then LLVM has a hard time proving that it's sound to elide, which makes it construct `T` on the stack first, and then copy it into the allocation. Create an uninit `Box` first, and then write `T::default` into it, so that LLVM now only needs to prove that the `T::default` can't panic, which should be trivial for most `Default` impls. --- library/alloc/src/boxed.rs | 2 +- tests/codegen/placement-new.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 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 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/tests/codegen/placement-new.rs b/tests/codegen/placement-new.rs index 68260a65a3f..d5c7969dd19 100644 --- a/tests/codegen/placement-new.rs +++ b/tests/codegen/placement-new.rs @@ -9,9 +9,9 @@ // CHECK-LABEL: @box_default_inplace #[no_mangle] pub fn box_default_inplace() -> Box<(String, String)> { - // CHECK: [[ALLOCA:%.*]] = alloca + // CHECK-NOT: alloca // CHECK: [[BOX:%.*]] = {{.*}}call {{.*}}__rust_alloc( - // CHECK: call void @llvm.memcpy{{.*}}(ptr {{.*}}[[BOX]], ptr {{.*}}[[ALLOCA]] + // CHECK-NOT: call void @llvm.memcpy // CHECK: ret ptr [[BOX]] Box::default() }