diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index d955b96d06af0..e5778f8a05d2e 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -116,29 +116,30 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { for debug_info in body.var_debug_info.iter_mut() { if let VarDebugInfoContents::Place(place) = &mut debug_info.value { let mut new_projections: Option> = None; - let mut last_deref = 0; - for (i, (base, elem)) in place.iter_projections().enumerate() { + for (base, elem) in place.iter_projections() { let base_ty = base.ty(&body.local_decls, tcx).ty; if elem == PlaceElem::Deref && base_ty.is_box() { - let new_projections = new_projections.get_or_insert_default(); + // Clone the projections before us, since now we need to mutate them. + let new_projections = + new_projections.get_or_insert_with(|| base.projection.to_vec()); let (unique_ty, nonnull_ty, ptr_ty) = build_ptr_tys(tcx, base_ty.boxed_ty(), unique_did, nonnull_did); - new_projections.extend_from_slice(&base.projection[last_deref..]); new_projections.extend_from_slice(&build_projection( unique_ty, nonnull_ty, ptr_ty, )); new_projections.push(PlaceElem::Deref); - - last_deref = i; + } else if let Some(new_projections) = new_projections.as_mut() { + // Keep building up our projections list once we've started it. + new_projections.push(elem); } } - if let Some(mut new_projections) = new_projections { - new_projections.extend_from_slice(&place.projection[last_deref..]); + // Store the mutated projections if we actually changed something. + if let Some(new_projections) = new_projections { place.projection = tcx.mk_place_elems(&new_projections); } } diff --git a/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff b/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff new file mode 100644 index 0000000000000..279c1a1990dc8 --- /dev/null +++ b/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff @@ -0,0 +1,13 @@ +- // MIR for `pointee` before ElaborateBoxDerefs ++ // MIR for `pointee` after ElaborateBoxDerefs + + fn pointee(_1: Box) -> () { +- debug foo => (*_1); ++ debug foo => (*(((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32)); + let mut _0: (); + + bb0: { + return; + } + } + diff --git a/tests/mir-opt/elaborate_box_deref_in_debuginfo.rs b/tests/mir-opt/elaborate_box_deref_in_debuginfo.rs new file mode 100644 index 0000000000000..0046e7104f1c6 --- /dev/null +++ b/tests/mir-opt/elaborate_box_deref_in_debuginfo.rs @@ -0,0 +1,20 @@ +// skip-filecheck +//@ test-mir-pass: ElaborateBoxDerefs + +#![feature(custom_mir, core_intrinsics)] + +extern crate core; +use core::intrinsics::mir::*; + +// EMIT_MIR elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff +#[custom_mir(dialect = "built")] +fn pointee(opt: Box) { + mir!( + debug foo => *opt; + { + Return() + } + ) +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs new file mode 100644 index 0000000000000..8b2de578b249f --- /dev/null +++ b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs @@ -0,0 +1,35 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ run-pass + +#![feature(async_closure)] + +extern crate block_on; + +pub trait Trait { + fn callback(&mut self); +} +impl Trait for (i32,) { + fn callback(&mut self) { + println!("hi {}", self.0); + self.0 += 1; + } +} + +async fn call_once(f: impl async FnOnce()) { + f().await; +} + +async fn run(mut loader: Box) { + let f = async move || { + loader.callback(); + loader.callback(); + }; + call_once(f).await; +} + +fn main() { + block_on::block_on(async { + run(Box::new((42,))).await; + }); +}