Auto merge of #128572 - compiler-errors:fix-elaborate-box-derefs-on-debug, r=saethlin
Fix `ElaborateBoxDerefs` on debug varinfo Slightly simplifies the `ElaborateBoxDerefs` pass to fix cases where it was applying the wrong projections to debug var infos containing places that deref boxes. From what I can tell[^1], we don't actually have any tests (or code anywhere, really) that exercise `debug x => *(...: Box<T>)`, and it's very difficult to trigger this in surface Rust, so I wrote a custom MIR test. What happens is that the pass was turning `*(SOME_PLACE: Box<T>)` into `*(*((((SOME_PLACE).0: Unique<T>).0: NonNull<T>).0: *const T))` in debug var infos. In particular, notice the *double deref*, which was wrong. This is the root cause of #128554, so this PR fixes #128554 as well. The reason that async closures was affected is because of the way that we compute the [`ByMove` body](https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs), which resulted in `*(...: Box<T>)` in debug var info. But this really has nothing to do with async closures. [^1]: Validated by literally replacing the `if elem == PlaceElem::Deref && base_ty.is_box() { ... }` innards with a `panic!()`, which compiled all of stage2 without panicking.
This commit is contained in:
commit
730d5d4095
4 changed files with 77 additions and 8 deletions
|
@ -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<Vec<_>> = 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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue