replace box_new in Box::new with write_via_move

requires lowering write_via_move during MIR building to make it just like an assignment
This commit is contained in:
Ralf Jung 2025-10-25 13:17:59 +02:00
parent 139651428d
commit 93d45480aa
12 changed files with 159 additions and 114 deletions

View file

@ -0,0 +1,76 @@
// MIR for `box_new` after CleanupPostBorrowck
fn box_new(_1: T) -> Box<[T; 1024]> {
debug x => _1;
let mut _0: std::boxed::Box<[T; 1024]>;
let mut _2: std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>>;
let mut _4: &mut std::mem::MaybeUninit<[T; 1024]>;
let mut _5: &mut std::mem::MaybeUninit<[T; 1024]>;
let _6: ();
let mut _7: *mut [T; 1024];
let mut _8: T;
let mut _9: std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>>;
scope 1 {
debug b => _2;
let _3: *mut [T; 1024];
scope 2 {
debug ptr => _3;
}
}
bb0: {
StorageLive(_2);
_2 = Box::<[T; 1024]>::new_uninit() -> [return: bb1, unwind: bb7];
}
bb1: {
nop;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
_5 = &mut (*_2);
_4 = &mut (*_5);
_3 = MaybeUninit::<[T; 1024]>::as_mut_ptr(move _4) -> [return: bb2, unwind: bb6];
}
bb2: {
StorageDead(_4);
nop;
StorageDead(_5);
StorageLive(_6);
StorageLive(_7);
_7 = copy _3;
StorageLive(_8);
_8 = copy _1;
(*_7) = [move _8; 1024];
StorageDead(_8);
StorageDead(_7);
StorageDead(_6);
StorageLive(_9);
_9 = move _2;
_0 = Box::<MaybeUninit<[T; 1024]>>::assume_init(move _9) -> [return: bb3, unwind: bb5];
}
bb3: {
StorageDead(_9);
StorageDead(_3);
drop(_2) -> [return: bb4, unwind: bb7];
}
bb4: {
StorageDead(_2);
return;
}
bb5 (cleanup): {
drop(_9) -> [return: bb6, unwind terminate(cleanup)];
}
bb6 (cleanup): {
drop(_2) -> [return: bb7, unwind terminate(cleanup)];
}
bb7 (cleanup): {
resume;
}
}

View file

@ -0,0 +1,23 @@
//! Ensure we don't generate unnecessary copys for `write_via_move`.
//@ compile-flags: -Zmir-opt-level=0
#![feature(core_intrinsics)]
use std::mem;
// Can't emit `built.after` here as that contains user type annotations which contain DefId that
// change all the time.
// EMIT_MIR write_via_move.box_new.CleanupPostBorrowck.after.mir
// CHECK-LABEL: fn box_new
#[inline(never)]
fn box_new<T: Copy>(x: T) -> Box<[T; 1024]> {
let mut b = Box::new_uninit();
let ptr = mem::MaybeUninit::as_mut_ptr(&mut *b);
// Ensure the array gets constructed directly into the deref'd pointer.
// CHECK: (*[[TEMP1:_.+]]) = [{{(move|copy) _.+}}; 1024];
unsafe { std::intrinsics::write_via_move(ptr, [x; 1024]) };
unsafe { b.assume_init() }
}
fn main() {
box_new(0);
}

View file

@ -213,7 +213,7 @@
+ StorageLive(_42);
+ _42 = Option::<()>::None;
+ _35 = copy ((*_37).0: std::option::Option<()>);
+ ((*_37).0: std::option::Option<()>) = copy _42;
+ ((*_37).0: std::option::Option<()>) = move _42;
+ StorageDead(_42);
+ StorageLive(_43);
+ _43 = discriminant(_35);

View file

@ -197,17 +197,6 @@ pub fn read_via_copy_uninhabited(r: &Never) -> Never {
unsafe { core::intrinsics::read_via_copy(r) }
}
// EMIT_MIR lower_intrinsics.write_via_move_string.LowerIntrinsics.diff
pub fn write_via_move_string(r: &mut String, v: String) {
// CHECK-LABEL: fn write_via_move_string(
// CHECK: [[ptr:_.*]] = &raw mut (*_1);
// CHECK: [[tmp:_.*]] = move _2;
// CHECK: (*[[ptr]]) = move [[tmp]];
// CHECK: return;
unsafe { core::intrinsics::write_via_move(r, v) }
}
pub enum Never {}
// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff

View file

@ -1,31 +0,0 @@
- // MIR for `write_via_move_string` before LowerIntrinsics
+ // MIR for `write_via_move_string` after LowerIntrinsics
fn write_via_move_string(_1: &mut String, _2: String) -> () {
debug r => _1;
debug v => _2;
let mut _0: ();
let mut _3: *mut std::string::String;
let mut _4: std::string::String;
bb0: {
StorageLive(_3);
_3 = &raw mut (*_1);
StorageLive(_4);
_4 = move _2;
- _0 = write_via_move::<String>(move _3, move _4) -> [return: bb1, unwind unreachable];
+ (*_3) = move _4;
+ goto -> bb1;
}
bb1: {
StorageDead(_4);
StorageDead(_3);
goto -> bb2;
}
bb2: {
return;
}
}

View file

@ -1,31 +0,0 @@
- // MIR for `write_via_move_string` before LowerIntrinsics
+ // MIR for `write_via_move_string` after LowerIntrinsics
fn write_via_move_string(_1: &mut String, _2: String) -> () {
debug r => _1;
debug v => _2;
let mut _0: ();
let mut _3: *mut std::string::String;
let mut _4: std::string::String;
bb0: {
StorageLive(_3);
_3 = &raw mut (*_1);
StorageLive(_4);
_4 = move _2;
- _0 = write_via_move::<String>(move _3, move _4) -> [return: bb1, unwind unreachable];
+ (*_3) = move _4;
+ goto -> bb1;
}
bb1: {
StorageDead(_4);
StorageDead(_3);
goto -> bb2;
}
bb2: {
return;
}
}

View file

@ -1,19 +1,24 @@
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::SIZE` failed here
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::ALIGN` failed here
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new_uninit_in`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::ALIGN` failed here
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::try_new_uninit_in`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new`
--> $DIR/issue-17913.rs:16:21
|
LL | let a: Box<_> = Box::new([&n; SIZE]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0080`.