From ed34b6f2db1ddec0c54b57fbb7e4803398a26d91 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 25 Oct 2025 13:17:59 +0200 Subject: [PATCH 1/3] lower write_via_move during MIR building to make it just like an assignment --- .../rustc_mir_build/src/builder/expr/into.rs | 27 ++++++- .../src/lower_intrinsics.rs | 25 +----- ...move.box_new.CleanupPostBorrowck.after.mir | 76 +++++++++++++++++++ tests/mir-opt/building/write_via_move.rs | 23 ++++++ tests/mir-opt/lower_intrinsics.rs | 11 --- ...ve_string.LowerIntrinsics.panic-abort.diff | 31 -------- ...e_string.LowerIntrinsics.panic-unwind.diff | 31 -------- 7 files changed, 126 insertions(+), 98 deletions(-) create mode 100644 tests/mir-opt/building/write_via_move.box_new.CleanupPostBorrowck.after.mir create mode 100644 tests/mir-opt/building/write_via_move.rs delete mode 100644 tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff delete mode 100644 tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index bb65ef28bdc8c..92e618c4f1329 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -9,8 +9,8 @@ use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::thir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty}; -use rustc_span::DUMMY_SP; use rustc_span::source_map::Spanned; +use rustc_span::{DUMMY_SP, sym}; use rustc_trait_selection::infer::InferCtxtExt; use tracing::{debug, instrument}; @@ -365,6 +365,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None }) } + // The `write_via_move` intrinsic needs to be special-cased very early to avoid + // introducing unnecessary copies that can be hard to remove again later: + // `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping. + ExprKind::Call { ty, fun, ref args, .. } + if let ty::FnDef(def_id, _generic_args) = ty.kind() + && let Some(intrinsic) = this.tcx.intrinsic(def_id) + && intrinsic.name == sym::write_via_move => + { + // We still have to evaluate the callee expression as normal (but we don't care + // about its result). + let _fun = unpack!(block = this.as_local_operand(block, fun)); + // The destination must have unit type (so we don't actually have to store anything + // into it). + assert!(destination.ty(&this.local_decls, this.tcx).ty.is_unit()); + + // Compile this to an assignment of the argument into the destination. + let [ptr, val] = **args else { + span_bug!(expr_span, "invalid write_via_move call") + }; + let Some(ptr) = unpack!(block = this.as_local_operand(block, ptr)).place() else { + span_bug!(expr_span, "invalid write_via_move call") + }; + let ptr_deref = ptr.project_deeper(&[ProjectionElem::Deref], this.tcx); + this.expr_into_dest(ptr_deref, block, val) + } ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => { let fun = unpack!(block = this.as_local_operand(block, fun)); let args: Box<[_]> = args diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index ad7c52064a8ef..8a4f83a6edb37 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -171,30 +171,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { Some(target) => TerminatorKind::Goto { target }, } } - sym::write_via_move => { - let target = target.unwrap(); - let Ok([ptr, val]) = take_array(args) else { - span_bug!( - terminator.source_info.span, - "Wrong number of arguments for write_via_move intrinsic", - ); - }; - let derefed_place = if let Some(place) = ptr.node.place() - && let Some(local) = place.as_local() - { - tcx.mk_place_deref(local.into()) - } else { - span_bug!( - terminator.source_info.span, - "Only passing a local is supported" - ); - }; - block.statements.push(Statement::new( - terminator.source_info, - StatementKind::Assign(Box::new((derefed_place, Rvalue::Use(val.node)))), - )); - terminator.kind = TerminatorKind::Goto { target }; - } + // `write_via_move` is already lowered during MIR building. sym::discriminant_value => { let target = target.unwrap(); let Ok([arg]) = take_array(args) else { diff --git a/tests/mir-opt/building/write_via_move.box_new.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/write_via_move.box_new.CleanupPostBorrowck.after.mir new file mode 100644 index 0000000000000..6a6e984023b75 --- /dev/null +++ b/tests/mir-opt/building/write_via_move.box_new.CleanupPostBorrowck.after.mir @@ -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>; + 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>; + 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::>::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; + } +} diff --git a/tests/mir-opt/building/write_via_move.rs b/tests/mir-opt/building/write_via_move.rs new file mode 100644 index 0000000000000..12be592a855c1 --- /dev/null +++ b/tests/mir-opt/building/write_via_move.rs @@ -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(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); +} diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 6b8c2a7902023..e8a7701477415 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -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 diff --git a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff deleted file mode 100644 index cc9177c90027d..0000000000000 --- a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-abort.diff +++ /dev/null @@ -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::(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ (*_3) = move _4; -+ goto -> bb1; - } - - bb1: { - StorageDead(_4); - StorageDead(_3); - goto -> bb2; - } - - bb2: { - return; - } - } - diff --git a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff deleted file mode 100644 index cc9177c90027d..0000000000000 --- a/tests/mir-opt/lower_intrinsics.write_via_move_string.LowerIntrinsics.panic-unwind.diff +++ /dev/null @@ -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::(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ (*_3) = move _4; -+ goto -> bb1; - } - - bb1: { - StorageDead(_4); - StorageDead(_3); - goto -> bb2; - } - - bb2: { - return; - } - } - From 16641f85600d2481cb1042b10b071d1f9ca9e9fb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 20 Oct 2025 14:27:49 +0200 Subject: [PATCH 2/3] replace box_new in Box::new with write_via_move --- library/alloc/src/alloc.rs | 6 +++++- library/alloc/src/boxed.rs | 12 ++++++++++-- ....run2-{closure#0}.Inline.panic-unwind.diff | 2 +- tests/ui/limits/issue-17913.32bit.stderr | 19 ++++++++++++------- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 39450f69ce30a..c72664f6f92e2 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -343,11 +343,15 @@ unsafe impl Allocator for Global { } /// The allocator for `Box`. +/// +/// # Safety +/// +/// `size` and `align` must satisfy the conditions in [`Layout::from_size_align`]. #[cfg(not(no_global_oom_handling))] #[lang = "exchange_malloc"] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { +pub(crate) unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; match Global.allocate(layout) { Ok(ptr) => ptr.as_mut_ptr(), diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ae43fbfe1d69e..b1b490a28c7a2 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -203,7 +203,7 @@ use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; -use crate::alloc::{AllocError, Allocator, Global, Layout}; +use crate::alloc::{AllocError, Allocator, Global, Layout, exchange_malloc}; use crate::raw_vec::RawVec; #[cfg(not(no_global_oom_handling))] use crate::str::from_boxed_utf8_unchecked; @@ -259,7 +259,15 @@ impl Box { #[rustc_diagnostic_item = "box_new"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn new(x: T) -> Self { - return box_new(x); + // SAFETY: the size and align of a valid type `T` are always valid for `Layout`. + let ptr = unsafe { + exchange_malloc(::SIZE, ::ALIGN) + } as *mut T; + // Nothing below can panic so we do not have to worry about deallocating `ptr`. + // SAFETY: we just allocated the box to store `x`. + unsafe { core::intrinsics::write_via_move(ptr, x) }; + // SAFETY: we just initialized `b`. + unsafe { mem::transmute(ptr) } } /// Constructs a new box with uninitialized contents. diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 59417ce646513..ffcb0014cec69 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -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); diff --git a/tests/ui/limits/issue-17913.32bit.stderr b/tests/ui/limits/issue-17913.32bit.stderr index 1311822d0d0c4..a5a3f925f069a 100644 --- a/tests/ui/limits/issue-17913.32bit.stderr +++ b/tests/ui/limits/issue-17913.32bit.stderr @@ -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 `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here + = note: evaluation of ` 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: evaluation of ` 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 -note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new` - --> $DIR/issue-17913.rs:16:21 +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 | -LL | let a: Box<_> = Box::new([&n; SIZE]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` 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 -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. From 5ba7e69ed25f6369f0ec1d685bef741394434d05 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 26 Oct 2025 11:04:37 +0100 Subject: [PATCH 3/3] add init_box_via_move intrinsic and use it for vec! This allows us to get rid of box_new entirely --- compiler/rustc_borrowck/src/type_check/mod.rs | 20 ++- .../rustc_hir_analysis/src/check/intrinsic.rs | 10 +- .../src/fn_ctxt/suggestions.rs | 1 + .../rustc_mir_build/src/builder/expr/into.rs | 116 +++++++++++-- compiler/rustc_mir_build/src/thir/cx/expr.rs | 20 +-- compiler/rustc_span/src/symbol.rs | 1 + library/alloc/src/alloc.rs | 17 -- library/alloc/src/boxed.rs | 60 +++++-- library/alloc/src/macros.rs | 11 +- src/tools/miri/tests/pass/vec.rs | 13 ++ src/tools/miri/tests/pass/vec.stack.stderr | 5 + src/tools/miri/tests/pass/vec.tree.stderr | 5 + .../mir-opt/box_expr.main.ElaborateDrops.diff | 89 ---------- tests/mir-opt/box_expr.rs | 39 ----- ...move.box_new.CleanupPostBorrowck.after.mir | 51 ++++++ tests/mir-opt/building/init_box_via_move.rs | 27 +++ ...ve.vec_macro.CleanupPostBorrowck.after.mir | 41 +++++ ..._by_subslice.CleanupPostBorrowck.after.mir | 68 ++++++++ ...e_out.move_out_by_subslice.built.after.mir | 99 ----------- ...out_from_end.CleanupPostBorrowck.after.mir | 68 ++++++++ ...move_out.move_out_from_end.built.after.mir | 99 ----------- .../building/uniform_array_move_out.rs | 11 +- .../boxes.main.GVN.panic-abort.diff | 59 ------- .../boxes.main.GVN.panic-unwind.diff | 63 ------- tests/mir-opt/const_prop/boxes.rs | 17 -- ...ng_operand.test.GVN.32bit.panic-abort.diff | 159 +++++++++--------- ...ng_operand.test.GVN.64bit.panic-abort.diff | 159 +++++++++--------- ...y.run2-{closure#0}.Inline.panic-abort.diff | 2 +- tests/mir-opt/issue_62289.rs | 3 +- ...test.ElaborateDrops.before.panic-abort.mir | 121 +++++++------ ...est.ElaborateDrops.before.panic-unwind.mir | 121 +++++++------ tests/ui/macros/vec-macro-in-pattern.rs | 2 +- tests/ui/macros/vec-macro-in-pattern.stderr | 12 +- tests/ui/span/regions-escape-loop-via-vec.rs | 6 +- .../span/regions-escape-loop-via-vec.stderr | 39 +---- tests/ui/unpretty/box.rs | 8 - tests/ui/unpretty/box.stdout | 90 ---------- 37 files changed, 773 insertions(+), 959 deletions(-) create mode 100644 src/tools/miri/tests/pass/vec.stack.stderr create mode 100644 src/tools/miri/tests/pass/vec.tree.stderr delete mode 100644 tests/mir-opt/box_expr.main.ElaborateDrops.diff delete mode 100644 tests/mir-opt/box_expr.rs create mode 100644 tests/mir-opt/building/init_box_via_move.box_new.CleanupPostBorrowck.after.mir create mode 100644 tests/mir-opt/building/init_box_via_move.rs create mode 100644 tests/mir-opt/building/init_box_via_move.vec_macro.CleanupPostBorrowck.after.mir create mode 100644 tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.CleanupPostBorrowck.after.mir delete mode 100644 tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir create mode 100644 tests/mir-opt/building/uniform_array_move_out.move_out_from_end.CleanupPostBorrowck.after.mir delete mode 100644 tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir delete mode 100644 tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff delete mode 100644 tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff delete mode 100644 tests/mir-opt/const_prop/boxes.rs delete mode 100644 tests/ui/unpretty/box.rs delete mode 100644 tests/ui/unpretty/box.stdout diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index d1d0bff8fe06b..acb905639d44d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1537,15 +1537,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } CastKind::Transmute => { - let ty_from = op.ty(self.body, tcx); - match ty_from.kind() { - ty::Pat(base, _) if base == ty => {} - _ => span_mirbug!( - self, - rvalue, - "Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR", - ), - } + // FIXME: `init_box_via_move` lowering really wants to use this. + // What do we have to do here? + // let ty_from = op.ty(self.body, tcx); + // match ty_from.kind() { + // ty::Pat(base, _) if base == ty => {} + // _ => span_mirbug!( + // self, + // rvalue, + // "Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR", + // ), + // } } CastKind::Subtype => { bug!("CastKind::Subtype shouldn't exist in borrowck") diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index a6659912e3fb9..45aa07e7f9021 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -76,7 +76,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::autodiff | sym::bitreverse | sym::black_box - | sym::box_new | sym::breakpoint | sym::bswap | sym::caller_location @@ -132,6 +131,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::forget | sym::frem_algebraic | sym::fsub_algebraic + | sym::init_box_via_move | sym::is_val_statically_known | sym::log2f16 | sym::log2f32 @@ -553,6 +553,12 @@ pub(crate) fn check_intrinsic_type( sym::write_via_move => { (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit) } + sym::init_box_via_move => { + let t = param(0); + let maybe_uninit_t = Ty::new_maybe_uninit(tcx, t); + + (1, 0, vec![Ty::new_box(tcx, maybe_uninit_t), param(0)], Ty::new_box(tcx, t)) + } sym::typed_swap_nonoverlapping => { (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit) @@ -645,8 +651,6 @@ pub(crate) fn check_intrinsic_type( sym::ub_checks => (0, 0, Vec::new(), tcx.types.bool), - sym::box_new => (1, 0, vec![param(0)], Ty::new_box(tcx, param(0))), - // contract_check_requires::(C) -> bool, where C: impl Fn() -> bool sym::contract_check_requires => (1, 0, vec![param(0)], tcx.types.unit), sym::contract_check_ensures => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5bb717a2a8281..407c3d9e8df6a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3022,6 +3022,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let deref_kind = if checked_ty.is_box() { // detect Box::new(..) + // FIXME: use `box_new` diagnostic item instead? if let ExprKind::Call(box_new, [_]) = expr.kind && let ExprKind::Path(qpath) = &box_new.kind && let Res::Def(DefKind::AssocFn, fn_id) = diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 92e618c4f1329..a19fb83a829fd 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -365,30 +365,112 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None }) } - // The `write_via_move` intrinsic needs to be special-cased very early to avoid - // introducing unnecessary copies that can be hard to remove again later: - // `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping. + // Some intrinsics are handled here because they desperately want to avoid introducing + // unnecessary copies. ExprKind::Call { ty, fun, ref args, .. } - if let ty::FnDef(def_id, _generic_args) = ty.kind() + if let ty::FnDef(def_id, generic_args) = ty.kind() && let Some(intrinsic) = this.tcx.intrinsic(def_id) - && intrinsic.name == sym::write_via_move => + && matches!(intrinsic.name, sym::write_via_move | sym::init_box_via_move) => { // We still have to evaluate the callee expression as normal (but we don't care // about its result). let _fun = unpack!(block = this.as_local_operand(block, fun)); - // The destination must have unit type (so we don't actually have to store anything - // into it). - assert!(destination.ty(&this.local_decls, this.tcx).ty.is_unit()); - // Compile this to an assignment of the argument into the destination. - let [ptr, val] = **args else { - span_bug!(expr_span, "invalid write_via_move call") - }; - let Some(ptr) = unpack!(block = this.as_local_operand(block, ptr)).place() else { - span_bug!(expr_span, "invalid write_via_move call") - }; - let ptr_deref = ptr.project_deeper(&[ProjectionElem::Deref], this.tcx); - this.expr_into_dest(ptr_deref, block, val) + match intrinsic.name { + sym::write_via_move => { + // `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping. + + // The destination must have unit type (so we don't actually have to store anything + // into it). + assert!(destination.ty(&this.local_decls, this.tcx).ty.is_unit()); + + // Compile this to an assignment of the argument into the destination. + let [ptr, val] = **args else { + span_bug!(expr_span, "invalid write_via_move call") + }; + let Some(ptr) = unpack!(block = this.as_local_operand(block, ptr)).place() + else { + span_bug!(expr_span, "invalid write_via_move call") + }; + let ptr_deref = ptr.project_deeper(&[ProjectionElem::Deref], this.tcx); + this.expr_into_dest(ptr_deref, block, val) + } + sym::init_box_via_move => { + // `write_via_move(b, val)` becomes + // ``` + // *transmute::<_, *mut T>(b) = val; + // transmute::<_, Box>(b) + // ``` + let t = generic_args.type_at(0); + let [b, val] = **args else { + span_bug!(expr_span, "invalid init_box_via_move call") + }; + let Some(b) = unpack!(block = this.as_local_operand(block, b)).place() + else { + span_bug!(expr_span, "invalid init_box_via_move call") + }; + // Project to the pointer inside `b`. We have to keep `b` in scope to ensure + // it gets dropped. After the first projection we can transmute which is + // easier. + let ty::Adt(box_adt_def, box_adt_args) = + b.ty(&this.local_decls, this.tcx).ty.kind() + else { + span_bug!(expr_span, "invalid init_box_via_move call") + }; + let unique_field = + this.tcx.adt_def(box_adt_def.did()).non_enum_variant().fields + [rustc_abi::FieldIdx::ZERO] + .did; + let Some(unique_def) = + this.tcx.type_of(unique_field).instantiate_identity().ty_adt_def() + else { + span_bug!( + this.tcx.def_span(unique_field), + "expected Box to contain Unique" + ) + }; + let unique_ty = + Ty::new_adt(this.tcx, unique_def, this.tcx.mk_args(&[box_adt_args[0]])); + let b_field = b.project_deeper( + &[ProjectionElem::Field(rustc_abi::FieldIdx::ZERO, unique_ty)], + this.tcx, + ); + // `ptr` is `b` transmuted to `*mut T`. + let ptr_ty = Ty::new_mut_ptr(this.tcx, t); + let ptr = this.local_decls.push(LocalDecl::new(ptr_ty, expr_span)); + this.cfg.push( + block, + Statement::new(source_info, StatementKind::StorageLive(ptr)), + ); + // Make sure `StorageDead` gets emitted. + this.schedule_drop_storage_and_value(expr_span, this.local_scope(), ptr); + this.cfg.push_assign( + block, + source_info, + Place::from(ptr), + // Needs to be a `Copy` so that `b` still gets dropped if `val` panics. + Rvalue::Cast(CastKind::Transmute, Operand::Copy(b_field), ptr_ty), + ); + // Store `val` into `ptr`. + let ptr_deref = + Place::from(ptr).project_deeper(&[ProjectionElem::Deref], this.tcx); + unpack!(block = this.expr_into_dest(ptr_deref, block, val)); + // Return `ptr` transmuted to `Box`. + this.cfg.push_assign( + block, + source_info, + destination, + Rvalue::Cast( + CastKind::Transmute, + // Move from `b` so that does not get dropped any more. + Operand::Move(b), + Ty::new_box(this.tcx, t), + ), + ); + block.unit() + } + _ => rustc_middle::bug!(), + } } ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => { let fun = unpack!(block = this.as_local_operand(block, fun)); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 0b9bc018a09b3..ce8f2b58ee704 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -20,7 +20,7 @@ use rustc_middle::ty::{ self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, }; use rustc_middle::{bug, span_bug}; -use rustc_span::{Span, sym}; +use rustc_span::Span; use tracing::{debug, info, instrument, trace}; use crate::errors::*; @@ -385,24 +385,6 @@ impl<'tcx> ThirBuildCx<'tcx> { from_hir_call: true, fn_span: expr.span, } - } else if let ty::FnDef(def_id, _) = self.typeck_results.expr_ty(fun).kind() - && let Some(intrinsic) = self.tcx.intrinsic(def_id) - && intrinsic.name == sym::box_new - { - // We don't actually evaluate `fun` here, so make sure that doesn't miss any side-effects. - if !matches!(fun.kind, hir::ExprKind::Path(_)) { - span_bug!( - expr.span, - "`box_new` intrinsic can only be called via path expression" - ); - } - let value = &args[0]; - return Expr { - temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, - ty: expr_ty, - span: expr.span, - kind: ExprKind::Box { value: self.mirror_expr(value) }, - }; } else { // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. let adt_data = if let hir::ExprKind::Path(ref qpath) = fun.kind diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 223d818a2949b..aa6443e850c92 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1233,6 +1233,7 @@ symbols! { infer_static_outlives_requirements, inherent_associated_types, inherit, + init_box_via_move, initial, inlateout, inline, diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index c72664f6f92e2..f966812f7386b 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -342,23 +342,6 @@ unsafe impl Allocator for Global { } } -/// The allocator for `Box`. -/// -/// # Safety -/// -/// `size` and `align` must satisfy the conditions in [`Layout::from_size_align`]. -#[cfg(not(no_global_oom_handling))] -#[lang = "exchange_malloc"] -#[inline] -#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces -pub(crate) unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { - let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; - match Global.allocate(layout) { - Ok(ptr) => ptr.as_mut_ptr(), - Err(_) => handle_alloc_error(layout), - } -} - // # Allocation error handler #[cfg(not(no_global_oom_handling))] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b1b490a28c7a2..4352f2d928c9e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -192,7 +192,7 @@ use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; use core::marker::{Tuple, Unsize}; -use core::mem::{self, SizedTypeProperties}; +use core::mem::{self, MaybeUninit, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver, @@ -203,7 +203,7 @@ use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; -use crate::alloc::{AllocError, Allocator, Global, Layout, exchange_malloc}; +use crate::alloc::{AllocError, Allocator, Global, Layout}; use crate::raw_vec::RawVec; #[cfg(not(no_global_oom_handling))] use crate::str::from_boxed_utf8_unchecked; @@ -233,14 +233,39 @@ pub struct Box< #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, >(Unique, A); -/// Constructs a `Box` by calling the `exchange_malloc` lang item and moving the argument into -/// the newly allocated memory. This is an intrinsic to avoid unnecessary copies. +/// Monomorphic function for allocating an uninit `Box`. /// -/// This is the surface syntax for `box ` expressions. -#[doc(hidden)] +/// # Safety +/// +/// size and align need to be safe for `Layout::from_size_align_unchecked`. +#[inline] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces +unsafe fn box_new_uninit(size: usize, align: usize) -> *mut u8 { + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; + match Global.allocate(layout) { + Ok(ptr) => ptr.as_mut_ptr(), + Err(_) => handle_alloc_error(layout), + } +} + +/// Writes `x` into `b`, then returns `b` at its new type`. +/// +/// This is needed for `vec!`, which can't afford any extra copies of the argument (or else debug +/// builds regress), has to be written fully as a call chain without `let` (or else the temporary +/// lifetimes of the arguments change), and can't use an `unsafe` block as that would then also +/// include the user-provided `$x`. #[rustc_intrinsic] #[unstable(feature = "liballoc_internals", issue = "none")] -pub fn box_new(x: T) -> Box; +pub fn init_box_via_move(b: Box>, x: T) -> Box; + +/// Helper for `vec!` to ensure type inferences work correctly (which it wouldn't if we +/// inlined the `as` cast). +#[doc(hidden)] +#[unstable(feature = "liballoc_internals", issue = "none")] +#[inline(always)] +pub fn box_array_into_vec(b: Box<[T; N]>) -> crate::vec::Vec { + (b as Box<[T]>).into_vec() +} impl Box { /// Allocates memory on the heap and then places `x` into it. @@ -259,9 +284,10 @@ impl Box { #[rustc_diagnostic_item = "box_new"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn new(x: T) -> Self { - // SAFETY: the size and align of a valid type `T` are always valid for `Layout`. + // This is `Box::new_uninit` but inlined to avoid build time regressions. + // SAFETY: The size and align of a valid type `T` are always valid for `Layout`. let ptr = unsafe { - exchange_malloc(::SIZE, ::ALIGN) + box_new_uninit(::SIZE, ::ALIGN) } as *mut T; // Nothing below can panic so we do not have to worry about deallocating `ptr`. // SAFETY: we just allocated the box to store `x`. @@ -285,9 +311,21 @@ impl Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] - #[inline] + #[inline(always)] + #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn new_uninit() -> Box> { - Self::new_uninit_in(Global) + // This is the same as `Self::new_uninit_in(Global)`, but manually inlined (just like + // `Box::new`). + + // SAFETY: + // - The size and align of a valid type `T` are always valid for `Layout`. + // - If `allocate` succeeds, the returned pointer exactly matches what `Box` needs. + unsafe { + mem::transmute(box_new_uninit( + ::SIZE, + ::ALIGN, + )) + } } /// Constructs a new `Box` with uninitialized contents, with the memory diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 1e6e2ae8c3675..44d869166528c 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -47,10 +47,15 @@ macro_rules! vec { $crate::vec::from_elem($elem, $n) ); ($($x:expr),+ $(,)?) => ( - <[_]>::into_vec( - // Using the intrinsic produces a dramatic improvement in stack usage for + $crate::boxed::box_array_into_vec( + // Using `init_box_via_move` produces a dramatic improvement in stack usage for // unoptimized programs using this code path to construct large Vecs. - $crate::boxed::box_new([$($x),+]) + // We can't use `write_via_move` because this entire invocation has to remain a call + // chain without `let` bindings, or else the temporary scopes change and things break; + // it also has to all be safe since `safe { ... }` blocks sadly are not a thing and we + // must not wrap `$x` in `unsafe` (also, wrapping `$x` in a safe block has a good chance + // of introducing extra moves so might not be a good call either). + $crate::boxed::init_box_via_move($crate::boxed::Box::new_uninit(), [$($x),+]) ) ); } diff --git a/src/tools/miri/tests/pass/vec.rs b/src/tools/miri/tests/pass/vec.rs index 8b1b1e143b16d..45ebaae7366f9 100644 --- a/src/tools/miri/tests/pass/vec.rs +++ b/src/tools/miri/tests/pass/vec.rs @@ -178,6 +178,18 @@ fn extract_if() { } } +fn vec_macro_cleanup() { + fn panic() -> T { + panic!() + } + // Ensure all memory gets deallocated on a panic: the `Box` we construct, and the `Box` + // constructed inside `vec!` to eventually turn into a `Vec`. + std::panic::catch_unwind(|| { + let _v = vec![Box::new(0), panic()]; + }) + .unwrap_err(); +} + fn main() { assert_eq!(vec_reallocate().len(), 5); @@ -209,4 +221,5 @@ fn main() { reverse(); miri_issue_2759(); extract_if(); + vec_macro_cleanup(); } diff --git a/src/tools/miri/tests/pass/vec.stack.stderr b/src/tools/miri/tests/pass/vec.stack.stderr new file mode 100644 index 0000000000000..8c6112f0dc4d1 --- /dev/null +++ b/src/tools/miri/tests/pass/vec.stack.stderr @@ -0,0 +1,5 @@ + +thread 'main' ($TID) panicked at tests/pass/vec.rs:LL:CC: +explicit panic +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/src/tools/miri/tests/pass/vec.tree.stderr b/src/tools/miri/tests/pass/vec.tree.stderr new file mode 100644 index 0000000000000..8c6112f0dc4d1 --- /dev/null +++ b/src/tools/miri/tests/pass/vec.tree.stderr @@ -0,0 +1,5 @@ + +thread 'main' ($TID) panicked at tests/pass/vec.rs:LL:CC: +explicit panic +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.diff b/tests/mir-opt/box_expr.main.ElaborateDrops.diff deleted file mode 100644 index 4fa77cf82d819..0000000000000 --- a/tests/mir-opt/box_expr.main.ElaborateDrops.diff +++ /dev/null @@ -1,89 +0,0 @@ -- // MIR for `main` before ElaborateDrops -+ // MIR for `main` after ElaborateDrops - - fn main() -> () { - let mut _0: (); - let _1: std::boxed::Box; - let mut _2: *mut u8; - let mut _3: std::boxed::Box; - let _4: (); - let mut _5: std::boxed::Box; -+ let mut _6: &mut std::boxed::Box; -+ let mut _7: (); -+ let mut _8: *const S; - scope 1 { - debug x => _1; - } - - bb0: { - StorageLive(_1); - _2 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageLive(_3); - _3 = ShallowInitBox(move _2, S); - (*_3) = S::new() -> [return: bb2, unwind: bb8]; - } - - bb2: { - _1 = move _3; -- drop(_3) -> [return: bb3, unwind continue]; -+ goto -> bb3; - } - - bb3: { - StorageDead(_3); - StorageLive(_4); - StorageLive(_5); - _5 = move _1; - _4 = std::mem::drop::>(move _5) -> [return: bb4, unwind: bb6]; - } - - bb4: { - StorageDead(_5); - StorageDead(_4); - _0 = const (); -- drop(_1) -> [return: bb5, unwind continue]; -+ goto -> bb5; - } - - bb5: { - StorageDead(_1); - return; - } - - bb6 (cleanup): { -- drop(_5) -> [return: bb7, unwind terminate(cleanup)]; -+ goto -> bb7; - } - - bb7 (cleanup): { -- drop(_1) -> [return: bb9, unwind terminate(cleanup)]; -+ goto -> bb9; - } - - bb8 (cleanup): { -- drop(_3) -> [return: bb9, unwind terminate(cleanup)]; -+ goto -> bb12; - } - - bb9 (cleanup): { - resume; -+ } -+ -+ bb10 (cleanup): { -+ _6 = &mut _3; -+ _7 = as Drop>::drop(move _6) -> [return: bb9, unwind terminate(cleanup)]; -+ } -+ -+ bb11 (cleanup): { -+ goto -> bb10; -+ } -+ -+ bb12 (cleanup): { -+ _8 = copy ((_3.0: std::ptr::Unique).0: std::ptr::NonNull) as *const S (Transmute); -+ goto -> bb11; - } - } - diff --git a/tests/mir-opt/box_expr.rs b/tests/mir-opt/box_expr.rs deleted file mode 100644 index 6299c98718094..0000000000000 --- a/tests/mir-opt/box_expr.rs +++ /dev/null @@ -1,39 +0,0 @@ -//@ test-mir-pass: ElaborateDrops -//@ needs-unwind - -#![feature(rustc_attrs, liballoc_internals)] - -// EMIT_MIR box_expr.main.ElaborateDrops.diff -fn main() { - // CHECK-LABEL: fn main( - // CHECK: [[ptr:_.*]] = move {{_.*}} as *const S (Transmute); - // CHECK: [[nonnull:_.*]] = NonNull:: { pointer: move [[ptr]] }; - // CHECK: [[unique:_.*]] = Unique:: { pointer: move [[nonnull]], _marker: const PhantomData:: }; - // CHECK: [[box:_.*]] = Box::(move [[unique]], const std::alloc::Global); - // CHECK: [[ptr:_.*]] = copy (([[box]].0: std::ptr::Unique).0: std::ptr::NonNull) as *const S (Transmute); - // CHECK: (*[[ptr]]) = S::new() -> [return: [[ret:bb.*]], unwind: [[unwind:bb.*]]]; - // CHECK: [[ret]]: { - // CHECK: [[box2:_.*]] = move [[box]]; - // CHECK: [[box3:_.*]] = move [[box2]]; - // CHECK: std::mem::drop::>(move [[box3]]) - // CHECK: [[unwind]] (cleanup): { - // CHECK: [[boxref:_.*]] = &mut [[box]]; - // CHECK: as Drop>::drop(move [[boxref]]) - - let x = std::boxed::box_new(S::new()); - drop(x); -} - -struct S; - -impl S { - fn new() -> Self { - S - } -} - -impl Drop for S { - fn drop(&mut self) { - println!("splat!"); - } -} diff --git a/tests/mir-opt/building/init_box_via_move.box_new.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/init_box_via_move.box_new.CleanupPostBorrowck.after.mir new file mode 100644 index 0000000000000..7c55541ca2717 --- /dev/null +++ b/tests/mir-opt/building/init_box_via_move.box_new.CleanupPostBorrowck.after.mir @@ -0,0 +1,51 @@ +// 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>; + let mut _3: std::boxed::Box>; + let mut _4: *mut [T; 1024]; + let mut _5: T; + scope 1 { + debug b => _2; + } + + bb0: { + StorageLive(_2); + _2 = Box::<[T; 1024]>::new_uninit() -> [return: bb1, unwind: bb5]; + } + + bb1: { + nop; + StorageLive(_3); + _3 = move _2; + StorageLive(_4); + _4 = copy (_3.0: std::ptr::Unique>) as *mut [T; 1024] (Transmute); + StorageLive(_5); + _5 = copy _1; + (*_4) = [move _5; 1024]; + StorageDead(_5); + _0 = move _3 as std::boxed::Box<[T; 1024]> (Transmute); + StorageDead(_4); + drop(_3) -> [return: bb2, unwind: bb4]; + } + + bb2: { + StorageDead(_3); + drop(_2) -> [return: bb3, unwind: bb5]; + } + + bb3: { + StorageDead(_2); + return; + } + + bb4 (cleanup): { + drop(_2) -> [return: bb5, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/init_box_via_move.rs b/tests/mir-opt/building/init_box_via_move.rs new file mode 100644 index 0000000000000..3b5c0cc48823d --- /dev/null +++ b/tests/mir-opt/building/init_box_via_move.rs @@ -0,0 +1,27 @@ +//! Ensure we don't generate unnecessary copys for `write_via_move`. +//@ compile-flags: -Zmir-opt-level=0 +#![feature(liballoc_internals)] + +// Can't emit `built.after` here as that contains user type annotations which contain DefId that +// change all the time. +// EMIT_MIR init_box_via_move.box_new.CleanupPostBorrowck.after.mir +// CHECK-LABEL: fn box_new +#[inline(never)] +fn box_new(x: T) -> Box<[T; 1024]> { + let mut b = Box::new_uninit(); + // Ensure the array gets constructed directly into the deref'd pointer. + // CHECK: (*[[TEMP1:_.+]]) = [{{(move|copy) _.+}}; 1024]; + std::boxed::init_box_via_move(b, [x; 1024]) +} + +// EMIT_MIR init_box_via_move.vec_macro.CleanupPostBorrowck.after.mir +// CHECK-LABEL: fn vec_macro +fn vec_macro() -> Vec { + // CHECK: (*[[TEMP1:_.+]]) = [const 0_i32, const 1_i32, + vec![0, 1, 2, 3, 4, 5, 6, 7] +} + +fn main() { + box_new(0); + vec_macro(); +} diff --git a/tests/mir-opt/building/init_box_via_move.vec_macro.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/init_box_via_move.vec_macro.CleanupPostBorrowck.after.mir new file mode 100644 index 0000000000000..1a860faac2fe6 --- /dev/null +++ b/tests/mir-opt/building/init_box_via_move.vec_macro.CleanupPostBorrowck.after.mir @@ -0,0 +1,41 @@ +// MIR for `vec_macro` after CleanupPostBorrowck + +fn vec_macro() -> Vec { + let mut _0: std::vec::Vec; + let mut _1: std::boxed::Box<[i32; 8]>; + let mut _2: std::boxed::Box>; + let mut _3: *mut [i32; 8]; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Box::<[i32; 8]>::new_uninit() -> [return: bb1, unwind: bb5]; + } + + bb1: { + StorageLive(_3); + _3 = copy (_2.0: std::ptr::Unique>) as *mut [i32; 8] (Transmute); + (*_3) = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32, const 6_i32, const 7_i32]; + _1 = move _2 as std::boxed::Box<[i32; 8]> (Transmute); + StorageDead(_3); + drop(_2) -> [return: bb2, unwind: bb4]; + } + + bb2: { + StorageDead(_2); + _0 = box_array_into_vec::(move _1) -> [return: bb3, unwind: bb4]; + } + + bb3: { + StorageDead(_1); + return; + } + + bb4 (cleanup): { + drop(_1) -> [return: bb5, unwind terminate(cleanup)]; + } + + bb5 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.CleanupPostBorrowck.after.mir new file mode 100644 index 0000000000000..17756938b889d --- /dev/null +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.CleanupPostBorrowck.after.mir @@ -0,0 +1,68 @@ +// MIR for `move_out_by_subslice` after CleanupPostBorrowck + +fn move_out_by_subslice() -> () { + let mut _0: (); + let _1: [std::boxed::Box; 2]; + let mut _2: std::boxed::Box; + let mut _3: std::boxed::Box; + scope 1 { + debug a => _1; + let _4: [std::boxed::Box; 2]; + scope 2 { + debug _y => _4; + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Box::::new(const 1_i32) -> [return: bb1, unwind: bb9]; + } + + bb1: { + StorageLive(_3); + _3 = Box::::new(const 2_i32) -> [return: bb2, unwind: bb8]; + } + + bb2: { + _1 = [move _2, move _3]; + drop(_3) -> [return: bb3, unwind: bb8]; + } + + bb3: { + StorageDead(_3); + drop(_2) -> [return: bb4, unwind: bb9]; + } + + bb4: { + StorageDead(_2); + nop; + PlaceMention(_1); + StorageLive(_4); + _4 = move _1[0..2]; + _0 = const (); + drop(_4) -> [return: bb5, unwind: bb7]; + } + + bb5: { + StorageDead(_4); + drop(_1) -> [return: bb6, unwind: bb9]; + } + + bb6: { + StorageDead(_1); + return; + } + + bb7 (cleanup): { + drop(_1) -> [return: bb9, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { + drop(_2) -> [return: bb9, unwind terminate(cleanup)]; + } + + bb9 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir deleted file mode 100644 index 839bdeca86a88..0000000000000 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir +++ /dev/null @@ -1,99 +0,0 @@ -// MIR for `move_out_by_subslice` after built - -fn move_out_by_subslice() -> () { - let mut _0: (); - let _1: [std::boxed::Box; 2]; - let mut _2: std::boxed::Box; - let mut _3: *mut u8; - let mut _4: std::boxed::Box; - let mut _5: std::boxed::Box; - let mut _6: *mut u8; - let mut _7: std::boxed::Box; - scope 1 { - debug a => _1; - let _8: [std::boxed::Box; 2]; - scope 2 { - debug _y => _8; - } - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - _3 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb1, unwind: bb13]; - } - - bb1: { - StorageLive(_4); - _4 = ShallowInitBox(move _3, i32); - (*_4) = const 1_i32; - _2 = move _4; - drop(_4) -> [return: bb2, unwind: bb12]; - } - - bb2: { - StorageDead(_4); - StorageLive(_5); - _6 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb3, unwind: bb12]; - } - - bb3: { - StorageLive(_7); - _7 = ShallowInitBox(move _6, i32); - (*_7) = const 2_i32; - _5 = move _7; - drop(_7) -> [return: bb4, unwind: bb11]; - } - - bb4: { - StorageDead(_7); - _1 = [move _2, move _5]; - drop(_5) -> [return: bb5, unwind: bb12]; - } - - bb5: { - StorageDead(_5); - drop(_2) -> [return: bb6, unwind: bb13]; - } - - bb6: { - StorageDead(_2); - FakeRead(ForLet(None), _1); - PlaceMention(_1); - StorageLive(_8); - _8 = move _1[0..2]; - _0 = const (); - drop(_8) -> [return: bb8, unwind: bb10]; - } - - bb7: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; - } - - bb8: { - StorageDead(_8); - drop(_1) -> [return: bb9, unwind: bb13]; - } - - bb9: { - StorageDead(_1); - return; - } - - bb10 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate(cleanup)]; - } - - bb11 (cleanup): { - drop(_5) -> [return: bb12, unwind terminate(cleanup)]; - } - - bb12 (cleanup): { - drop(_2) -> [return: bb13, unwind terminate(cleanup)]; - } - - bb13 (cleanup): { - resume; - } -} diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.CleanupPostBorrowck.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.CleanupPostBorrowck.after.mir new file mode 100644 index 0000000000000..79e0f0af0dbc8 --- /dev/null +++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.CleanupPostBorrowck.after.mir @@ -0,0 +1,68 @@ +// MIR for `move_out_from_end` after CleanupPostBorrowck + +fn move_out_from_end() -> () { + let mut _0: (); + let _1: [std::boxed::Box; 2]; + let mut _2: std::boxed::Box; + let mut _3: std::boxed::Box; + scope 1 { + debug a => _1; + let _4: std::boxed::Box; + scope 2 { + debug _y => _4; + } + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Box::::new(const 1_i32) -> [return: bb1, unwind: bb9]; + } + + bb1: { + StorageLive(_3); + _3 = Box::::new(const 2_i32) -> [return: bb2, unwind: bb8]; + } + + bb2: { + _1 = [move _2, move _3]; + drop(_3) -> [return: bb3, unwind: bb8]; + } + + bb3: { + StorageDead(_3); + drop(_2) -> [return: bb4, unwind: bb9]; + } + + bb4: { + StorageDead(_2); + nop; + PlaceMention(_1); + StorageLive(_4); + _4 = move _1[1 of 2]; + _0 = const (); + drop(_4) -> [return: bb5, unwind: bb7]; + } + + bb5: { + StorageDead(_4); + drop(_1) -> [return: bb6, unwind: bb9]; + } + + bb6: { + StorageDead(_1); + return; + } + + bb7 (cleanup): { + drop(_1) -> [return: bb9, unwind terminate(cleanup)]; + } + + bb8 (cleanup): { + drop(_2) -> [return: bb9, unwind terminate(cleanup)]; + } + + bb9 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir deleted file mode 100644 index 7fda69c7500a3..0000000000000 --- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir +++ /dev/null @@ -1,99 +0,0 @@ -// MIR for `move_out_from_end` after built - -fn move_out_from_end() -> () { - let mut _0: (); - let _1: [std::boxed::Box; 2]; - let mut _2: std::boxed::Box; - let mut _3: *mut u8; - let mut _4: std::boxed::Box; - let mut _5: std::boxed::Box; - let mut _6: *mut u8; - let mut _7: std::boxed::Box; - scope 1 { - debug a => _1; - let _8: std::boxed::Box; - scope 2 { - debug _y => _8; - } - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - _3 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb1, unwind: bb13]; - } - - bb1: { - StorageLive(_4); - _4 = ShallowInitBox(move _3, i32); - (*_4) = const 1_i32; - _2 = move _4; - drop(_4) -> [return: bb2, unwind: bb12]; - } - - bb2: { - StorageDead(_4); - StorageLive(_5); - _6 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb3, unwind: bb12]; - } - - bb3: { - StorageLive(_7); - _7 = ShallowInitBox(move _6, i32); - (*_7) = const 2_i32; - _5 = move _7; - drop(_7) -> [return: bb4, unwind: bb11]; - } - - bb4: { - StorageDead(_7); - _1 = [move _2, move _5]; - drop(_5) -> [return: bb5, unwind: bb12]; - } - - bb5: { - StorageDead(_5); - drop(_2) -> [return: bb6, unwind: bb13]; - } - - bb6: { - StorageDead(_2); - FakeRead(ForLet(None), _1); - PlaceMention(_1); - StorageLive(_8); - _8 = move _1[1 of 2]; - _0 = const (); - drop(_8) -> [return: bb8, unwind: bb10]; - } - - bb7: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; - } - - bb8: { - StorageDead(_8); - drop(_1) -> [return: bb9, unwind: bb13]; - } - - bb9: { - StorageDead(_1); - return; - } - - bb10 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate(cleanup)]; - } - - bb11 (cleanup): { - drop(_5) -> [return: bb12, unwind terminate(cleanup)]; - } - - bb12 (cleanup): { - drop(_2) -> [return: bb13, unwind terminate(cleanup)]; - } - - bb13 (cleanup): { - resume; - } -} diff --git a/tests/mir-opt/building/uniform_array_move_out.rs b/tests/mir-opt/building/uniform_array_move_out.rs index 36245273fe1c1..573e64f26dcb6 100644 --- a/tests/mir-opt/building/uniform_array_move_out.rs +++ b/tests/mir-opt/building/uniform_array_move_out.rs @@ -1,16 +1,17 @@ //@ compile-flags: -Zmir-opt-level=0 // skip-filecheck -#![feature(liballoc_internals, rustc_attrs)] -// EMIT_MIR uniform_array_move_out.move_out_from_end.built.after.mir +// Can't emit `built.after` here as that contains user type annotations which contain DefId that +// change all the time. +// EMIT_MIR uniform_array_move_out.move_out_from_end.CleanupPostBorrowck.after.mir fn move_out_from_end() { - let a = [std::boxed::box_new(1), std::boxed::box_new(2)]; + let a = [Box::new(1), Box::new(2)]; let [.., _y] = a; } -// EMIT_MIR uniform_array_move_out.move_out_by_subslice.built.after.mir +// EMIT_MIR uniform_array_move_out.move_out_by_subslice.CleanupPostBorrowck.after.mir fn move_out_by_subslice() { - let a = [std::boxed::box_new(1), std::boxed::box_new(2)]; + let a = [Box::new(1), Box::new(2)]; let [_y @ ..] = a; } diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff deleted file mode 100644 index 95eaf18b4703b..0000000000000 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-abort.diff +++ /dev/null @@ -1,59 +0,0 @@ -- // MIR for `main` before GVN -+ // MIR for `main` after GVN - - fn main() -> () { - let mut _0: (); - let _1: i32; - let mut _2: i32; - let mut _3: std::boxed::Box; - let mut _4: *mut u8; - let mut _5: std::boxed::Box; - let mut _6: *const i32; - let mut _7: std::ptr::NonNull; - let mut _8: std::ptr::Unique; - let mut _9: *const i32; - let mut _10: *const i32; - scope 1 { - debug x => _1; - } - - bb0: { - StorageLive(_1); -- StorageLive(_2); -+ nop; - StorageLive(_3); - _4 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageLive(_5); -- _6 = move _4 as *const i32 (Transmute); -- _7 = NonNull:: { pointer: move _6 }; -- _8 = Unique:: { pointer: move _7, _marker: const PhantomData:: }; -+ _6 = copy _4 as *const i32 (PtrToPtr); -+ _7 = NonNull:: { pointer: copy _6 }; -+ _8 = Unique:: { pointer: copy _7, _marker: const PhantomData:: }; - _5 = Box::(move _8, const std::alloc::Global); -- _9 = copy ((_5.0: std::ptr::Unique).0: std::ptr::NonNull) as *const i32 (Transmute); -- (*_9) = const 42_i32; -+ _9 = copy _6; -+ (*_6) = const 42_i32; - _3 = move _5; - StorageDead(_5); - _10 = copy ((_3.0: std::ptr::Unique).0: std::ptr::NonNull) as *const i32 (Transmute); - _2 = copy (*_10); -- _1 = Add(move _2, const 0_i32); -- StorageDead(_2); -+ _1 = copy _2; -+ nop; - drop(_3) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_3); - _0 = const (); - StorageDead(_1); - return; - } - } - diff --git a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff deleted file mode 100644 index 6d8d3a0dcfe29..0000000000000 --- a/tests/mir-opt/const_prop/boxes.main.GVN.panic-unwind.diff +++ /dev/null @@ -1,63 +0,0 @@ -- // MIR for `main` before GVN -+ // MIR for `main` after GVN - - fn main() -> () { - let mut _0: (); - let _1: i32; - let mut _2: i32; - let mut _3: std::boxed::Box; - let mut _4: *mut u8; - let mut _5: std::boxed::Box; - let mut _6: *const i32; - let mut _7: std::ptr::NonNull; - let mut _8: std::ptr::Unique; - let mut _9: *const i32; - let mut _10: *const i32; - scope 1 { - debug x => _1; - } - - bb0: { - StorageLive(_1); -- StorageLive(_2); -+ nop; - StorageLive(_3); - _4 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageLive(_5); -- _6 = move _4 as *const i32 (Transmute); -- _7 = NonNull:: { pointer: move _6 }; -- _8 = Unique:: { pointer: move _7, _marker: const PhantomData:: }; -+ _6 = copy _4 as *const i32 (PtrToPtr); -+ _7 = NonNull:: { pointer: copy _6 }; -+ _8 = Unique:: { pointer: copy _7, _marker: const PhantomData:: }; - _5 = Box::(move _8, const std::alloc::Global); -- _9 = copy ((_5.0: std::ptr::Unique).0: std::ptr::NonNull) as *const i32 (Transmute); -- (*_9) = const 42_i32; -+ _9 = copy _6; -+ (*_6) = const 42_i32; - _3 = move _5; - StorageDead(_5); - _10 = copy ((_3.0: std::ptr::Unique).0: std::ptr::NonNull) as *const i32 (Transmute); - _2 = copy (*_10); -- _1 = Add(move _2, const 0_i32); -- StorageDead(_2); -+ _1 = copy _2; -+ nop; - drop(_3) -> [return: bb2, unwind: bb3]; - } - - bb2: { - StorageDead(_3); - _0 = const (); - StorageDead(_1); - return; - } - - bb3 (cleanup): { - resume; - } - } - diff --git a/tests/mir-opt/const_prop/boxes.rs b/tests/mir-opt/const_prop/boxes.rs deleted file mode 100644 index a192d6b4133a2..0000000000000 --- a/tests/mir-opt/const_prop/boxes.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ test-mir-pass: GVN -//@ compile-flags: -O -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY - -#![feature(rustc_attrs, liballoc_internals)] - -// Note: this test verifies that we, in fact, do not const prop `#[rustc_box]` - -// EMIT_MIR boxes.main.GVN.diff -fn main() { - // CHECK-LABEL: fn main( - // CHECK: debug x => [[x:_.*]]; - // CHECK: (*{{_.*}}) = const 42_i32; - // CHECK: [[tmp:_.*]] = copy (*{{_.*}}); - // CHECK: [[x]] = copy [[tmp]]; - let x = *(std::boxed::box_new(42)) + 0; -} diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 38beb81e1ead2..4d9a8bc9c002e 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -11,9 +11,9 @@ let mut _9: *const [()]; let mut _10: std::boxed::Box<()>; let mut _11: *const (); + let mut _15: usize; let mut _16: usize; - let mut _17: usize; - let mut _27: usize; + let mut _26: usize; scope 1 { debug vp_ctx => _1; let _5: *const (); @@ -26,48 +26,49 @@ scope 4 { debug _x => _8; } - scope 18 (inlined foo) { - let mut _28: *const [()]; + scope 19 (inlined foo) { + let mut _27: *const [()]; } } - scope 16 (inlined slice_from_raw_parts::<()>) { - scope 17 (inlined std::ptr::from_raw_parts::<[()], ()>) { + scope 17 (inlined slice_from_raw_parts::<()>) { + scope 18 (inlined std::ptr::from_raw_parts::<[()], ()>) { } } } } scope 5 (inlined Box::<()>::new) { - let mut _12: *mut u8; - let mut _13: *const (); - let mut _14: std::ptr::NonNull<()>; - let mut _15: std::ptr::Unique<()>; - scope 6 (inlined alloc::alloc::exchange_malloc) { - let _18: std::alloc::Layout; - let mut _19: std::result::Result, std::alloc::AllocError>; - let mut _20: isize; - let mut _22: !; - scope 7 { - let _21: std::ptr::NonNull<[u8]>; - scope 8 { - scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { - scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { - scope 13 (inlined NonNull::<[u8]>::cast::) { - let mut _26: *mut [u8]; - scope 14 (inlined NonNull::<[u8]>::as_ptr) { + let _12: std::boxed::Box>; + let mut _13: *mut u8; + let mut _14: *mut (); + scope 6 { + } + scope 7 (inlined boxed::box_new_uninit) { + let _17: std::alloc::Layout; + let mut _18: std::result::Result, std::alloc::AllocError>; + let mut _19: isize; + let mut _21: !; + scope 8 { + let _20: std::ptr::NonNull<[u8]>; + scope 9 { + scope 12 (inlined NonNull::<[u8]>::as_mut_ptr) { + scope 13 (inlined NonNull::<[u8]>::as_non_null_ptr) { + scope 14 (inlined NonNull::<[u8]>::cast::) { + let mut _25: *mut [u8]; + scope 15 (inlined NonNull::<[u8]>::as_ptr) { } } } - scope 15 (inlined NonNull::::as_ptr) { + scope 16 (inlined NonNull::::as_ptr) { } } } - scope 10 (inlined ::allocate) { + scope 11 (inlined ::allocate) { } } - scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) { - let mut _23: bool; - let _24: (); - let mut _25: std::ptr::Alignment; + scope 10 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _22: bool; + let _23: (); + let mut _24: std::ptr::Alignment; } } } @@ -82,22 +83,20 @@ + _4 = const (); StorageLive(_12); StorageLive(_13); - StorageLive(_14); StorageLive(_15); +- _15 = const <() as std::mem::SizedTypeProperties>::SIZE; ++ _15 = const 0_usize; StorageLive(_16); -- _16 = const <() as std::mem::SizedTypeProperties>::SIZE; -+ _16 = const 0_usize; +- _16 = const <() as std::mem::SizedTypeProperties>::ALIGN; ++ _16 = const 1_usize; StorageLive(_17); -- _17 = const <() as std::mem::SizedTypeProperties>::ALIGN; -+ _17 = const 1_usize; - StorageLive(_18); + StorageLive(_19); StorageLive(_20); StorageLive(_21); - StorageLive(_22); - StorageLive(_24); StorageLive(_23); - _23 = UbChecks(); - switchInt(move _23) -> [0: bb6, otherwise: bb5]; + StorageLive(_22); + _22 = UbChecks(); + switchInt(move _22) -> [0: bb6, otherwise: bb5]; } bb1: { @@ -111,36 +110,32 @@ } bb3: { -- _22 = handle_alloc_error(move _18) -> unwind unreachable; -+ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; +- _21 = handle_alloc_error(move _17) -> unwind unreachable; ++ _21 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; } bb4: { - _21 = copy ((_19 as Ok).0: std::ptr::NonNull<[u8]>); -- StorageLive(_26); -+ nop; - _26 = copy _21 as *mut [u8] (Transmute); - _12 = copy _26 as *mut u8 (PtrToPtr); -- StorageDead(_26); -+ nop; - StorageDead(_19); - StorageDead(_24); - StorageDead(_22); + _20 = copy ((_18 as Ok).0: std::ptr::NonNull<[u8]>); + StorageLive(_25); + _25 = copy _20 as *mut [u8] (Transmute); + _13 = copy _25 as *mut u8 (PtrToPtr); + StorageDead(_25); + StorageDead(_18); + StorageDead(_23); StorageDead(_21); StorageDead(_20); - StorageDead(_18); + StorageDead(_19); StorageDead(_17); StorageDead(_16); -- _13 = copy _12 as *const () (PtrToPtr); -+ _13 = copy _26 as *const () (PtrToPtr); - _14 = NonNull::<()> { pointer: copy _13 }; - _15 = Unique::<()> { pointer: copy _14, _marker: const PhantomData::<()> }; - _3 = Box::<()>(move _15, const std::alloc::Global); -- (*_13) = move _4; -+ (*_13) = const (); StorageDead(_15); - StorageDead(_14); + _12 = copy _13 as std::boxed::Box> (Transmute); StorageDead(_13); + StorageLive(_14); + _14 = copy (_12.0: std::ptr::Unique>) as *mut () (Transmute); +- (*_14) = move _4; ++ (*_14) = const (); + _3 = copy _12 as std::boxed::Box<()> (Transmute); + StorageDead(_14); StorageDead(_12); StorageDead(_4); _2 = &_3; @@ -157,21 +152,21 @@ + nop; StorageLive(_7); _7 = copy _5; - StorageLive(_27); - _27 = const 1_usize; -- _6 = *const [()] from (copy _7, copy _27); + StorageLive(_26); + _26 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _26); + _6 = *const [()] from (copy _5, const 1_usize); - StorageDead(_27); + StorageDead(_26); StorageDead(_7); StorageLive(_8); StorageLive(_9); _9 = copy _6; - StorageLive(_28); -- _28 = copy _9; + StorageLive(_27); +- _27 = copy _9; - _8 = copy _9 as *mut () (PtrToPtr); -+ _28 = copy _6; ++ _27 = copy _6; + _8 = copy _5 as *mut () (PtrToPtr); - StorageDead(_28); + StorageDead(_27); StorageDead(_9); _0 = const (); StorageDead(_8); @@ -183,26 +178,26 @@ } bb5: { -- _24 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable]; -+ _24 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; +- _23 = Layout::from_size_align_unchecked::precondition_check(copy _15, copy _16) -> [return: bb6, unwind unreachable]; ++ _23 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_23); - StorageLive(_25); -- _25 = copy _17 as std::ptr::Alignment (Transmute); -- _18 = Layout { size: copy _16, align: move _25 }; -+ _25 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); -+ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; - StorageDead(_25); - StorageLive(_19); -- _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _18, const false) -> [return: bb7, unwind unreachable]; -+ _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; + StorageDead(_22); + StorageLive(_24); +- _24 = copy _16 as std::ptr::Alignment (Transmute); +- _17 = Layout { size: copy _15, align: move _24 }; ++ _24 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); ++ _17 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; + StorageDead(_24); + StorageLive(_18); +- _18 = std::alloc::Global::alloc_impl(const std::boxed::box_new_uninit::promoted[0], copy _17, const false) -> [return: bb7, unwind unreachable]; ++ _18 = std::alloc::Global::alloc_impl(const std::boxed::box_new_uninit::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; } bb7: { - _20 = discriminant(_19); - switchInt(move _20) -> [0: bb4, 1: bb3, otherwise: bb2]; + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb4, 1: bb3, otherwise: bb2]; } + } + diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 047579cdb5094..b3ef5cafa5696 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -11,9 +11,9 @@ let mut _9: *const [()]; let mut _10: std::boxed::Box<()>; let mut _11: *const (); + let mut _15: usize; let mut _16: usize; - let mut _17: usize; - let mut _27: usize; + let mut _26: usize; scope 1 { debug vp_ctx => _1; let _5: *const (); @@ -26,48 +26,49 @@ scope 4 { debug _x => _8; } - scope 18 (inlined foo) { - let mut _28: *const [()]; + scope 19 (inlined foo) { + let mut _27: *const [()]; } } - scope 16 (inlined slice_from_raw_parts::<()>) { - scope 17 (inlined std::ptr::from_raw_parts::<[()], ()>) { + scope 17 (inlined slice_from_raw_parts::<()>) { + scope 18 (inlined std::ptr::from_raw_parts::<[()], ()>) { } } } } scope 5 (inlined Box::<()>::new) { - let mut _12: *mut u8; - let mut _13: *const (); - let mut _14: std::ptr::NonNull<()>; - let mut _15: std::ptr::Unique<()>; - scope 6 (inlined alloc::alloc::exchange_malloc) { - let _18: std::alloc::Layout; - let mut _19: std::result::Result, std::alloc::AllocError>; - let mut _20: isize; - let mut _22: !; - scope 7 { - let _21: std::ptr::NonNull<[u8]>; - scope 8 { - scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { - scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { - scope 13 (inlined NonNull::<[u8]>::cast::) { - let mut _26: *mut [u8]; - scope 14 (inlined NonNull::<[u8]>::as_ptr) { + let _12: std::boxed::Box>; + let mut _13: *mut u8; + let mut _14: *mut (); + scope 6 { + } + scope 7 (inlined boxed::box_new_uninit) { + let _17: std::alloc::Layout; + let mut _18: std::result::Result, std::alloc::AllocError>; + let mut _19: isize; + let mut _21: !; + scope 8 { + let _20: std::ptr::NonNull<[u8]>; + scope 9 { + scope 12 (inlined NonNull::<[u8]>::as_mut_ptr) { + scope 13 (inlined NonNull::<[u8]>::as_non_null_ptr) { + scope 14 (inlined NonNull::<[u8]>::cast::) { + let mut _25: *mut [u8]; + scope 15 (inlined NonNull::<[u8]>::as_ptr) { } } } - scope 15 (inlined NonNull::::as_ptr) { + scope 16 (inlined NonNull::::as_ptr) { } } } - scope 10 (inlined ::allocate) { + scope 11 (inlined ::allocate) { } } - scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) { - let mut _23: bool; - let _24: (); - let mut _25: std::ptr::Alignment; + scope 10 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _22: bool; + let _23: (); + let mut _24: std::ptr::Alignment; } } } @@ -82,22 +83,20 @@ + _4 = const (); StorageLive(_12); StorageLive(_13); - StorageLive(_14); StorageLive(_15); +- _15 = const <() as std::mem::SizedTypeProperties>::SIZE; ++ _15 = const 0_usize; StorageLive(_16); -- _16 = const <() as std::mem::SizedTypeProperties>::SIZE; -+ _16 = const 0_usize; +- _16 = const <() as std::mem::SizedTypeProperties>::ALIGN; ++ _16 = const 1_usize; StorageLive(_17); -- _17 = const <() as std::mem::SizedTypeProperties>::ALIGN; -+ _17 = const 1_usize; - StorageLive(_18); + StorageLive(_19); StorageLive(_20); StorageLive(_21); - StorageLive(_22); - StorageLive(_24); StorageLive(_23); - _23 = UbChecks(); - switchInt(move _23) -> [0: bb6, otherwise: bb5]; + StorageLive(_22); + _22 = UbChecks(); + switchInt(move _22) -> [0: bb6, otherwise: bb5]; } bb1: { @@ -111,36 +110,32 @@ } bb3: { -- _22 = handle_alloc_error(move _18) -> unwind unreachable; -+ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; +- _21 = handle_alloc_error(move _17) -> unwind unreachable; ++ _21 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; } bb4: { - _21 = copy ((_19 as Ok).0: std::ptr::NonNull<[u8]>); -- StorageLive(_26); -+ nop; - _26 = copy _21 as *mut [u8] (Transmute); - _12 = copy _26 as *mut u8 (PtrToPtr); -- StorageDead(_26); -+ nop; - StorageDead(_19); - StorageDead(_24); - StorageDead(_22); + _20 = copy ((_18 as Ok).0: std::ptr::NonNull<[u8]>); + StorageLive(_25); + _25 = copy _20 as *mut [u8] (Transmute); + _13 = copy _25 as *mut u8 (PtrToPtr); + StorageDead(_25); + StorageDead(_18); + StorageDead(_23); StorageDead(_21); StorageDead(_20); - StorageDead(_18); + StorageDead(_19); StorageDead(_17); StorageDead(_16); -- _13 = copy _12 as *const () (PtrToPtr); -+ _13 = copy _26 as *const () (PtrToPtr); - _14 = NonNull::<()> { pointer: copy _13 }; - _15 = Unique::<()> { pointer: copy _14, _marker: const PhantomData::<()> }; - _3 = Box::<()>(move _15, const std::alloc::Global); -- (*_13) = move _4; -+ (*_13) = const (); StorageDead(_15); - StorageDead(_14); + _12 = copy _13 as std::boxed::Box> (Transmute); StorageDead(_13); + StorageLive(_14); + _14 = copy (_12.0: std::ptr::Unique>) as *mut () (Transmute); +- (*_14) = move _4; ++ (*_14) = const (); + _3 = copy _12 as std::boxed::Box<()> (Transmute); + StorageDead(_14); StorageDead(_12); StorageDead(_4); _2 = &_3; @@ -157,21 +152,21 @@ + nop; StorageLive(_7); _7 = copy _5; - StorageLive(_27); - _27 = const 1_usize; -- _6 = *const [()] from (copy _7, copy _27); + StorageLive(_26); + _26 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _26); + _6 = *const [()] from (copy _5, const 1_usize); - StorageDead(_27); + StorageDead(_26); StorageDead(_7); StorageLive(_8); StorageLive(_9); _9 = copy _6; - StorageLive(_28); -- _28 = copy _9; + StorageLive(_27); +- _27 = copy _9; - _8 = copy _9 as *mut () (PtrToPtr); -+ _28 = copy _6; ++ _27 = copy _6; + _8 = copy _5 as *mut () (PtrToPtr); - StorageDead(_28); + StorageDead(_27); StorageDead(_9); _0 = const (); StorageDead(_8); @@ -183,26 +178,26 @@ } bb5: { -- _24 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable]; -+ _24 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; +- _23 = Layout::from_size_align_unchecked::precondition_check(copy _15, copy _16) -> [return: bb6, unwind unreachable]; ++ _23 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_23); - StorageLive(_25); -- _25 = copy _17 as std::ptr::Alignment (Transmute); -- _18 = Layout { size: copy _16, align: move _25 }; -+ _25 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); -+ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; - StorageDead(_25); - StorageLive(_19); -- _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _18, const false) -> [return: bb7, unwind unreachable]; -+ _19 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; + StorageDead(_22); + StorageLive(_24); +- _24 = copy _16 as std::ptr::Alignment (Transmute); +- _17 = Layout { size: copy _15, align: move _24 }; ++ _24 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); ++ _17 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; + StorageDead(_24); + StorageLive(_18); +- _18 = std::alloc::Global::alloc_impl(const std::boxed::box_new_uninit::promoted[0], copy _17, const false) -> [return: bb7, unwind unreachable]; ++ _18 = std::alloc::Global::alloc_impl(const std::boxed::box_new_uninit::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; } bb7: { - _20 = discriminant(_19); - switchInt(move _20) -> [0: bb4, 1: bb3, otherwise: bb2]; + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb4, 1: bb3, otherwise: bb2]; } + } + diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 4c1b25c786efc..b5d0dc186293b 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -202,7 +202,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); diff --git a/tests/mir-opt/issue_62289.rs b/tests/mir-opt/issue_62289.rs index d020c2cedca01..c0c85feb935c2 100644 --- a/tests/mir-opt/issue_62289.rs +++ b/tests/mir-opt/issue_62289.rs @@ -7,7 +7,8 @@ // EMIT_MIR issue_62289.test.ElaborateDrops.before.mir fn test() -> Option> { - Some(std::boxed::box_new(None?)) + let b = Box::new_uninit(); + Some(std::boxed::init_box_via_move(b, None?)) } fn main() { diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir index c46549c5742f2..14ce3cda9c592 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-abort.mir @@ -2,46 +2,53 @@ fn test() -> Option> { let mut _0: std::option::Option>; - let mut _1: std::boxed::Box; - let mut _2: *mut u8; - let mut _3: std::boxed::Box; - let mut _4: std::ops::ControlFlow, u32>; - let mut _5: std::option::Option; - let mut _6: isize; - let _7: std::option::Option; - let mut _8: !; - let mut _9: std::option::Option; - let _10: u32; + let _1: std::boxed::Box>; + let mut _2: std::boxed::Box; + let mut _3: std::boxed::Box>; + let mut _4: *mut u32; + let mut _5: std::ops::ControlFlow, u32>; + let mut _6: std::option::Option; + let mut _7: isize; + let mut _9: !; + let mut _10: std::option::Option; scope 1 { - debug residual => _7; + debug b => _1; + let _8: std::option::Option; + let _11: u32; scope 2 { + debug residual => _8; + scope 3 { + } } - } - scope 3 { - debug val => _10; scope 4 { + debug val => _11; + scope 5 { + } } } bb0: { StorageLive(_1); - _2 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb1, unwind: bb13]; + _1 = Box::::new_uninit() -> [return: bb1, unwind: bb16]; } bb1: { + StorageLive(_2); StorageLive(_3); - _3 = ShallowInitBox(move _2, u32); + _3 = move _1; StorageLive(_4); + _4 = copy (_3.0: std::ptr::Unique>) as *mut u32 (Transmute); StorageLive(_5); - _5 = Option::::None; - _4 = as Try>::branch(move _5) -> [return: bb2, unwind: bb12]; + StorageLive(_6); + _6 = Option::::None; + _5 = as Try>::branch(move _6) -> [return: bb2, unwind: bb14]; } bb2: { - StorageDead(_5); - PlaceMention(_4); - _6 = discriminant(_4); - switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb3]; + StorageDead(_6); + PlaceMention(_5); + _7 = discriminant(_5); + switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb3]; } bb3: { @@ -49,60 +56,76 @@ fn test() -> Option> { } bb4: { - StorageLive(_10); - _10 = copy ((_4 as Continue).0: u32); - (*_3) = copy _10; - StorageDead(_10); - _1 = move _3; - drop(_3) -> [return: bb7, unwind: bb11]; + StorageLive(_11); + _11 = copy ((_5 as Continue).0: u32); + (*_4) = copy _11; + StorageDead(_11); + _2 = move _3 as std::boxed::Box (Transmute); + StorageDead(_4); + drop(_3) -> [return: bb7, unwind: bb13]; } bb5: { - StorageLive(_7); - _7 = copy ((_4 as Break).0: std::option::Option); - StorageLive(_9); - _9 = copy _7; - _0 = > as FromResidual>>::from_residual(move _9) -> [return: bb6, unwind: bb12]; + StorageLive(_8); + _8 = copy ((_5 as Break).0: std::option::Option); + StorageLive(_10); + _10 = copy _8; + _0 = > as FromResidual>>::from_residual(move _10) -> [return: bb6, unwind: bb14]; } bb6: { - StorageDead(_9); - StorageDead(_7); - drop(_3) -> [return: bb9, unwind: bb13]; + StorageDead(_10); + StorageDead(_8); + StorageDead(_4); + drop(_3) -> [return: bb10, unwind: bb15]; } bb7: { StorageDead(_3); - _0 = Option::>::Some(move _1); - drop(_1) -> [return: bb8, unwind: bb13]; + _0 = Option::>::Some(move _2); + drop(_2) -> [return: bb8, unwind: bb15]; } bb8: { - StorageDead(_1); - StorageDead(_4); - goto -> bb10; + StorageDead(_2); + drop(_1) -> [return: bb9, unwind: bb16]; } bb9: { - StorageDead(_3); StorageDead(_1); - StorageDead(_4); - goto -> bb10; + StorageDead(_5); + goto -> bb12; } bb10: { - return; + StorageDead(_3); + StorageDead(_2); + drop(_1) -> [return: bb11, unwind: bb16]; } - bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate(cleanup)]; + bb11: { + StorageDead(_1); + StorageDead(_5); + goto -> bb12; } - bb12 (cleanup): { - drop(_3) -> [return: bb13, unwind terminate(cleanup)]; + bb12: { + return; } bb13 (cleanup): { + drop(_2) -> [return: bb15, unwind terminate(cleanup)]; + } + + bb14 (cleanup): { + drop(_3) -> [return: bb15, unwind terminate(cleanup)]; + } + + bb15 (cleanup): { + drop(_1) -> [return: bb16, unwind terminate(cleanup)]; + } + + bb16 (cleanup): { resume; } } diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir index 9f26debdbb6d6..d710514889ae3 100644 --- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir +++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.panic-unwind.mir @@ -2,46 +2,53 @@ fn test() -> Option> { let mut _0: std::option::Option>; - let mut _1: std::boxed::Box; - let mut _2: *mut u8; - let mut _3: std::boxed::Box; - let mut _4: std::ops::ControlFlow, u32>; - let mut _5: std::option::Option; - let mut _6: isize; - let _7: std::option::Option; - let mut _8: !; - let mut _9: std::option::Option; - let _10: u32; + let _1: std::boxed::Box>; + let mut _2: std::boxed::Box; + let mut _3: std::boxed::Box>; + let mut _4: *mut u32; + let mut _5: std::ops::ControlFlow, u32>; + let mut _6: std::option::Option; + let mut _7: isize; + let mut _9: !; + let mut _10: std::option::Option; scope 1 { - debug residual => _7; + debug b => _1; + let _8: std::option::Option; + let _11: u32; scope 2 { + debug residual => _8; + scope 3 { + } } - } - scope 3 { - debug val => _10; scope 4 { + debug val => _11; + scope 5 { + } } } bb0: { StorageLive(_1); - _2 = alloc::alloc::exchange_malloc(const ::SIZE, const ::ALIGN) -> [return: bb1, unwind continue]; + _1 = Box::::new_uninit() -> [return: bb1, unwind continue]; } bb1: { + StorageLive(_2); StorageLive(_3); - _3 = ShallowInitBox(move _2, u32); + _3 = move _1; StorageLive(_4); + _4 = copy (_3.0: std::ptr::Unique>) as *mut u32 (Transmute); StorageLive(_5); - _5 = Option::::None; - _4 = as Try>::branch(move _5) -> [return: bb2, unwind: bb12]; + StorageLive(_6); + _6 = Option::::None; + _5 = as Try>::branch(move _6) -> [return: bb2, unwind: bb14]; } bb2: { - StorageDead(_5); - PlaceMention(_4); - _6 = discriminant(_4); - switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb3]; + StorageDead(_6); + PlaceMention(_5); + _7 = discriminant(_5); + switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb3]; } bb3: { @@ -49,60 +56,76 @@ fn test() -> Option> { } bb4: { - StorageLive(_10); - _10 = copy ((_4 as Continue).0: u32); - (*_3) = copy _10; - StorageDead(_10); - _1 = move _3; - drop(_3) -> [return: bb7, unwind: bb11]; + StorageLive(_11); + _11 = copy ((_5 as Continue).0: u32); + (*_4) = copy _11; + StorageDead(_11); + _2 = move _3 as std::boxed::Box (Transmute); + StorageDead(_4); + drop(_3) -> [return: bb7, unwind: bb13]; } bb5: { - StorageLive(_7); - _7 = copy ((_4 as Break).0: std::option::Option); - StorageLive(_9); - _9 = copy _7; - _0 = > as FromResidual>>::from_residual(move _9) -> [return: bb6, unwind: bb12]; + StorageLive(_8); + _8 = copy ((_5 as Break).0: std::option::Option); + StorageLive(_10); + _10 = copy _8; + _0 = > as FromResidual>>::from_residual(move _10) -> [return: bb6, unwind: bb14]; } bb6: { - StorageDead(_9); - StorageDead(_7); - drop(_3) -> [return: bb9, unwind continue]; + StorageDead(_10); + StorageDead(_8); + StorageDead(_4); + drop(_3) -> [return: bb10, unwind: bb15]; } bb7: { StorageDead(_3); - _0 = Option::>::Some(move _1); - drop(_1) -> [return: bb8, unwind continue]; + _0 = Option::>::Some(move _2); + drop(_2) -> [return: bb8, unwind: bb15]; } bb8: { - StorageDead(_1); - StorageDead(_4); - goto -> bb10; + StorageDead(_2); + drop(_1) -> [return: bb9, unwind continue]; } bb9: { - StorageDead(_3); StorageDead(_1); - StorageDead(_4); - goto -> bb10; + StorageDead(_5); + goto -> bb12; } bb10: { - return; + StorageDead(_3); + StorageDead(_2); + drop(_1) -> [return: bb11, unwind continue]; } - bb11 (cleanup): { - drop(_1) -> [return: bb13, unwind terminate(cleanup)]; + bb11: { + StorageDead(_1); + StorageDead(_5); + goto -> bb12; } - bb12 (cleanup): { - drop(_3) -> [return: bb13, unwind terminate(cleanup)]; + bb12: { + return; } bb13 (cleanup): { + drop(_2) -> [return: bb15, unwind terminate(cleanup)]; + } + + bb14 (cleanup): { + drop(_3) -> [return: bb15, unwind terminate(cleanup)]; + } + + bb15 (cleanup): { + drop(_1) -> [return: bb16, unwind terminate(cleanup)]; + } + + bb16 (cleanup): { resume; } } diff --git a/tests/ui/macros/vec-macro-in-pattern.rs b/tests/ui/macros/vec-macro-in-pattern.rs index 9b9a1edf54c9e..0e9cb087f66a3 100644 --- a/tests/ui/macros/vec-macro-in-pattern.rs +++ b/tests/ui/macros/vec-macro-in-pattern.rs @@ -6,7 +6,7 @@ fn main() { match Some(vec![42]) { Some(vec![43]) => {} //~ ERROR expected a pattern, found a function call //~| ERROR found associated function - //~| ERROR usage of qualified paths in this context is experimental + //~| ERROR expected a pattern, found a function call _ => {} } } diff --git a/tests/ui/macros/vec-macro-in-pattern.stderr b/tests/ui/macros/vec-macro-in-pattern.stderr index 71ba0ea5ad4f5..26291aaac8f4b 100644 --- a/tests/ui/macros/vec-macro-in-pattern.stderr +++ b/tests/ui/macros/vec-macro-in-pattern.stderr @@ -7,18 +7,16 @@ LL | Some(vec![43]) => {} = note: function calls are not allowed in patterns: = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0658]: usage of qualified paths in this context is experimental +error[E0532]: expected a pattern, found a function call --> $DIR/vec-macro-in-pattern.rs:7:14 | LL | Some(vec![43]) => {} - | ^^^^^^^^ + | ^^^^^^^^ not a tuple struct or tuple variant | - = note: see issue #86935 for more information - = help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: function calls are not allowed in patterns: = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0164]: expected tuple struct or tuple variant, found associated function `<[_]>::into_vec` +error[E0164]: expected tuple struct or tuple variant, found associated function `::alloc::boxed::Box::new_uninit` --> $DIR/vec-macro-in-pattern.rs:7:14 | LL | Some(vec![43]) => {} @@ -29,5 +27,5 @@ LL | Some(vec![43]) => {} error: aborting due to 3 previous errors -Some errors have detailed explanations: E0164, E0532, E0658. +Some errors have detailed explanations: E0164, E0532. For more information about an error, try `rustc --explain E0164`. diff --git a/tests/ui/span/regions-escape-loop-via-vec.rs b/tests/ui/span/regions-escape-loop-via-vec.rs index 1fceb09696770..fb1747751ecd3 100644 --- a/tests/ui/span/regions-escape-loop-via-vec.rs +++ b/tests/ui/span/regions-escape-loop-via-vec.rs @@ -2,11 +2,11 @@ fn broken() { let mut x = 3; let mut _y = vec![&mut x]; - while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed - let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed + while x < 10 { + let mut z = x; _y.push(&mut z); //~^ ERROR `z` does not live long enough - x += 1; //~ ERROR cannot use `x` because it was mutably borrowed + x += 1; } } diff --git a/tests/ui/span/regions-escape-loop-via-vec.stderr b/tests/ui/span/regions-escape-loop-via-vec.stderr index 18c6cd4809303..781f970ea5dcf 100644 --- a/tests/ui/span/regions-escape-loop-via-vec.stderr +++ b/tests/ui/span/regions-escape-loop-via-vec.stderr @@ -1,25 +1,3 @@ -error[E0503]: cannot use `x` because it was mutably borrowed - --> $DIR/regions-escape-loop-via-vec.rs:5:11 - | -LL | let mut _y = vec![&mut x]; - | ------ `x` is borrowed here -LL | while x < 10 { - | ^ use of borrowed `x` -LL | let mut z = x; -LL | _y.push(&mut z); - | -- borrow later used here - -error[E0503]: cannot use `x` because it was mutably borrowed - --> $DIR/regions-escape-loop-via-vec.rs:6:21 - | -LL | let mut _y = vec![&mut x]; - | ------ `x` is borrowed here -LL | while x < 10 { -LL | let mut z = x; - | ^ use of borrowed `x` -LL | _y.push(&mut z); - | -- borrow later used here - error[E0597]: `z` does not live long enough --> $DIR/regions-escape-loop-via-vec.rs:7:17 | @@ -33,19 +11,6 @@ LL | _y.push(&mut z); LL | } | - `z` dropped here while still borrowed -error[E0503]: cannot use `x` because it was mutably borrowed - --> $DIR/regions-escape-loop-via-vec.rs:9:9 - | -LL | let mut _y = vec![&mut x]; - | ------ `x` is borrowed here -... -LL | _y.push(&mut z); - | -- borrow later used here -LL | -LL | x += 1; - | ^^^^^^ use of borrowed `x` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0503, E0597. -For more information about an error, try `rustc --explain E0503`. +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/unpretty/box.rs b/tests/ui/unpretty/box.rs deleted file mode 100644 index 83fdeff7a1796..0000000000000 --- a/tests/ui/unpretty/box.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ compile-flags: -Zunpretty=thir-tree -//@ check-pass - -#![feature(liballoc_internals)] - -fn main() { - let _ = std::boxed::box_new(1); -} diff --git a/tests/ui/unpretty/box.stdout b/tests/ui/unpretty/box.stdout deleted file mode 100644 index 92155d0c73b9d..0000000000000 --- a/tests/ui/unpretty/box.stdout +++ /dev/null @@ -1,90 +0,0 @@ -DefId(0:3 ~ box[efb9]::main): -params: [ -] -body: - Expr { - ty: () - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(11)), backwards_incompatible: None } - span: $DIR/box.rs:6:11: 8:2 (#0) - kind: - Scope { - region_scope: Node(11) - lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).11)) - value: - Expr { - ty: () - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(11)), backwards_incompatible: None } - span: $DIR/box.rs:6:11: 8:2 (#0) - kind: - Block { - targeted_by_break: false - span: $DIR/box.rs:6:11: 8:2 (#0) - region_scope: Node(1) - safety_mode: Safe - stmts: [ - Stmt { - kind: Let { - remainder_scope: Remainder { block: 1, first_statement_index: 0} - init_scope: Node(2) - pattern: - Pat: { - ty: std::boxed::Box - span: $DIR/box.rs:7:9: 7:10 (#0) - kind: PatKind { - Wild - } - } - , - initializer: Some( - Expr { - ty: std::boxed::Box - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } - span: $DIR/box.rs:7:13: 7:35 (#0) - kind: - Scope { - region_scope: Node(3) - lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).3)) - value: - Expr { - ty: std::boxed::Box - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } - span: $DIR/box.rs:7:13: 7:35 (#0) - kind: - Box { - Expr { - ty: i32 - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } - span: $DIR/box.rs:7:33: 7:34 (#0) - kind: - Scope { - region_scope: Node(8) - lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).8)) - value: - Expr { - ty: i32 - temp_lifetime: TempLifetime { temp_lifetime: Some(Node(2)), backwards_incompatible: None } - span: $DIR/box.rs:7:33: 7:34 (#0) - kind: - Literal( lit: Spanned { node: Int(Pu128(1), Unsuffixed), span: $DIR/box.rs:7:33: 7:34 (#0) }, neg: false) - - } - } - } - } - } - } - } - ) - else_block: None - lint_level: Explicit(HirId(DefId(0:3 ~ box[efb9]::main).9)) - span: $DIR/box.rs:7:5: 7:35 (#0) - } - } - ] - expr: [] - } - } - } - } - -