Skip to content

Commit 1881b82

Browse files
committed
use compoundplace in debuginfo
1 parent a528517 commit 1881b82

File tree

18 files changed

+365
-77
lines changed

18 files changed

+365
-77
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
558558
err: &mut Diag<'infcx>,
559559
) {
560560
let var_info = self.body.var_debug_info.iter().find(|info| match info.value {
561-
VarDebugInfoContents::Place(ref p) => p == place,
561+
VarDebugInfoContents::Place(ref p) => p
562+
.projection_chain
563+
.iter()
564+
.flatten()
565+
.enumerate()
566+
.all(|(i, elem)| place.projection.get(i) == Some(&elem)),
562567
_ => false,
563568
});
564569
let arg_name = if let Some(var_info) = var_info {

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
491491
} else {
492492
match var.value {
493493
mir::VarDebugInfoContents::Place(place) => {
494-
self.monomorphized_place_ty(place.as_ref())
494+
let tcx = bx.tcx();
495+
let place_ty = place.ty(self.mir, tcx);
496+
self.monomorphize(place_ty.ty)
495497
}
496498
mir::VarDebugInfoContents::Const(c) => self.monomorphize(c.ty()),
497499
}
@@ -501,7 +503,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
501503
let var_kind = if let Some(arg_index) = var.argument_index
502504
&& var.composite.is_none()
503505
&& let mir::VarDebugInfoContents::Place(place) = var.value
504-
&& place.projection.is_empty()
506+
&& place.as_local().is_some()
505507
{
506508
let arg_index = arg_index as usize;
507509
if target_is_msvc {
@@ -566,7 +568,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
566568
source_info: var.source_info,
567569
dbg_var,
568570
fragment,
569-
projection: place.projection,
571+
// FIXME change field to be projection chain
572+
projection: bx
573+
.tcx()
574+
.mk_place_elems_from_iter(place.projection_chain.iter().flatten()),
570575
});
571576
}
572577
mir::VarDebugInfoContents::Const(c) => {

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,8 +1187,8 @@ impl<'tcx> LocalDecl<'tcx> {
11871187

11881188
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
11891189
pub enum VarDebugInfoContents<'tcx> {
1190-
/// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
1191-
Place(Place<'tcx>),
1190+
/// This `CompoundPlace` only contains projection which satisfy `can_use_in_debuginfo`.
1191+
Place(CompoundPlace<'tcx>),
11921192
Const(ConstOperand<'tcx>),
11931193
}
11941194

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 119 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Functionality for statements, operands, places, and things that appear in them.
22
3+
use smallvec::SmallVec;
34
use tracing::{debug, instrument};
45

56
use super::interpret::GlobalAlloc;
@@ -558,7 +559,7 @@ impl From<Local> for PlaceRef<'_> {
558559
/// A place possibly containing derefs in the middle of its projection by chaining projection lists.
559560
///
560561
/// In `AnalysisPhase::PostCleanup` and later, [`Place`] and [`PlaceRef`] cannot represent these
561-
/// kinds of places.
562+
/// kinds of places, requiring this struct to be used instead.
562563
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable, TypeFoldable, TypeVisitable)]
563564
pub struct CompoundPlace<'tcx> {
564565
pub local: Local,
@@ -579,6 +580,35 @@ pub struct CompoundPlaceRef<'tcx> {
579580

580581
// these impls are bare-bones for now
581582
impl<'tcx> CompoundPlace<'tcx> {
583+
pub fn from_place(place: Place<'tcx>, tcx: TyCtxt<'tcx>) -> CompoundPlace<'tcx> {
584+
let mut segment_start = 0;
585+
// size picked from sole user
586+
let mut new_projection_chain = SmallVec::<[_; 2]>::new();
587+
588+
for (i, elem) in place.projection.iter().enumerate() {
589+
if elem == PlaceElem::Deref && i > 0 {
590+
new_projection_chain.push(tcx.mk_place_elems(&place.projection[segment_start..i]));
591+
segment_start = i;
592+
}
593+
}
594+
595+
if segment_start == 0 {
596+
new_projection_chain.push(place.projection);
597+
} else {
598+
new_projection_chain.push(tcx.mk_place_elems(&place.projection[segment_start..]));
599+
}
600+
601+
if cfg!(debug_assertions) {
602+
let new_projections: Vec<_> = new_projection_chain.iter().copied().flatten().collect();
603+
assert_eq!(new_projections.as_slice(), place.projection.as_slice());
604+
}
605+
606+
CompoundPlace {
607+
local: place.local,
608+
projection_chain: tcx.mk_place_elem_chain(&new_projection_chain),
609+
}
610+
}
611+
582612
pub fn as_ref(&self) -> CompoundPlaceRef<'tcx> {
583613
let (last, base) = self
584614
.projection_chain
@@ -589,21 +619,75 @@ impl<'tcx> CompoundPlace<'tcx> {
589619
CompoundPlaceRef { local: self.local, projection_chain_base: base, last_projection: last }
590620
}
591621

622+
pub fn as_local(&self) -> Option<Local> {
623+
if self.projection_chain.is_empty() { Some(self.local) } else { None }
624+
}
625+
626+
pub fn local_or_deref_local(&self) -> Option<Local> {
627+
self.as_ref().local_or_deref_local()
628+
}
629+
630+
/// Returns a [`Place`] with only the first segment in the projection chain.
631+
pub fn base_place(&self) -> Place<'tcx> {
632+
Place {
633+
local: self.local,
634+
projection: self.projection_chain.first().copied().unwrap_or_default(),
635+
}
636+
}
637+
638+
/// Replaces the local and first segment of the projection with `new_base`.
639+
pub fn replace_base_place(&mut self, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
640+
self.local = new_base.local;
641+
self.projection_chain =
642+
match (new_base.projection.is_empty(), self.projection_chain.is_empty()) {
643+
(false, false) => {
644+
let mut new_projection_chain = self.projection_chain.to_vec();
645+
new_projection_chain[0] = new_base.projection;
646+
tcx.mk_place_elem_chain(&new_projection_chain)
647+
}
648+
(false, true) => tcx.mk_place_elem_chain(&[new_base.projection]),
649+
650+
(true, false) => tcx.mk_place_elem_chain(&self.projection_chain[1..]),
651+
(true, true) => List::empty(),
652+
}
653+
// FIXME: this logic is a mess
654+
// maybe seperate out projection before first deref?
655+
}
656+
657+
/// Replaces the local with `new_base`.
658+
pub fn replace_local_with_place(&mut self, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
659+
let base_place = self.base_place();
660+
661+
if new_base.projection.is_empty() {
662+
self.local = new_base.local;
663+
} else if base_place.is_indirect_first_projection() {
664+
let mut new_projection_chain = Vec::with_capacity(self.projection_chain.len() + 1);
665+
new_projection_chain.push(new_base.projection);
666+
new_projection_chain.extend_from_slice(self.projection_chain);
667+
668+
self.local = new_base.local;
669+
self.projection_chain = tcx.mk_place_elem_chain(&new_projection_chain);
670+
} else {
671+
self.replace_base_place(new_base.project_deeper(base_place.projection, tcx), tcx);
672+
}
673+
}
674+
592675
pub fn iter_projections(
593676
self,
594677
) -> impl Iterator<Item = (CompoundPlaceRef<'tcx>, PlaceElem<'tcx>)> + DoubleEndedIterator {
595678
self.projection_chain.iter().enumerate().flat_map(move |(i, projs)| {
596679
projs.iter().enumerate().map(move |(j, elem)| {
597680
let base = if j == 0 && i > 0 {
598681
// last_projection should only be empty if projection_chain_base is too
599-
// otherwise it has to have a deref at least
600-
601682
debug_assert_eq!(elem, PlaceElem::Deref);
602683
CompoundPlaceRef {
603684
local: self.local,
604685
projection_chain_base: &self.projection_chain[..i - 1],
605-
last_projection: &projs[..=j],
686+
last_projection: &self.projection_chain[i - 1],
606687
}
688+
689+
// FIXME: the fact that i messed up this logic the first time is good evidence that
690+
// the invariants are confusing and difficult to uphold
607691
} else {
608692
CompoundPlaceRef {
609693
local: self.local,
@@ -612,6 +696,19 @@ impl<'tcx> CompoundPlace<'tcx> {
612696
}
613697
};
614698

699+
if cfg!(debug_assertions) {
700+
let self_projections: Vec<_> = self.projection_chain.iter().flatten().collect();
701+
let base_projections: Vec<_> = base
702+
.projection_chain_base
703+
.iter()
704+
.copied()
705+
.flatten()
706+
.chain(base.last_projection.iter().copied())
707+
.collect();
708+
709+
assert_eq!(self_projections[..base_projections.len()], base_projections);
710+
}
711+
615712
(base, elem)
616713
})
617714
})
@@ -626,6 +723,13 @@ impl<'tcx> CompoundPlace<'tcx> {
626723
}
627724
}
628725

726+
impl From<Local> for CompoundPlace<'_> {
727+
#[inline]
728+
fn from(local: Local) -> Self {
729+
CompoundPlace { local, projection_chain: List::empty() }
730+
}
731+
}
732+
629733
impl<'tcx> CompoundPlaceRef<'tcx> {
630734
pub fn ty<D: ?Sized>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> PlaceTy<'tcx>
631735
where
@@ -635,6 +739,17 @@ impl<'tcx> CompoundPlaceRef<'tcx> {
635739
.projection_chain_ty(tcx, self.projection_chain_base)
636740
.multi_projection_ty(tcx, self.last_projection)
637741
}
742+
743+
pub fn local_or_deref_local(&self) -> Option<Local> {
744+
match *self {
745+
CompoundPlaceRef {
746+
local,
747+
projection_chain_base: [],
748+
last_projection: [] | [ProjectionElem::Deref],
749+
} => Some(local),
750+
_ => None,
751+
}
752+
}
638753
}
639754

640755
///////////////////////////////////////////////////////////////////////////

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,7 @@ macro_rules! make_mir_visitor {
923923
match value {
924924
VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
925925
VarDebugInfoContents::Place(place) =>
926-
self.visit_place(
926+
self.visit_compound_place(
927927
place,
928928
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
929929
location

compiler/rustc_middle/src/ty/codec.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,21 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
298298
}
299299
}
300300

301+
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::CompoundPlace<'tcx> {
302+
fn decode(decoder: &mut D) -> Self {
303+
let local: mir::Local = Decodable::decode(decoder);
304+
let chain_len = decoder.read_usize();
305+
let projection_chain =
306+
decoder.interner().mk_place_elem_chain_from_iter((0..chain_len).map(|_| {
307+
let projs_len = decoder.read_usize();
308+
decoder.interner().mk_place_elems_from_iter(
309+
(0..projs_len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
310+
)
311+
}));
312+
mir::CompoundPlace { local, projection_chain }
313+
}
314+
}
315+
301316
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> {
302317
fn decode(decoder: &mut D) -> Self {
303318
ty::Region::new_from_kind(decoder.interner(), Decodable::decode(decoder))

compiler/rustc_mir_build/src/builder/custom/parse.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
260260
let operand = self.parse_operand(operand)?;
261261
let value = match operand {
262262
Operand::Constant(c) => VarDebugInfoContents::Const(*c),
263-
Operand::Copy(p) | Operand::Move(p) => VarDebugInfoContents::Place(p),
263+
Operand::Copy(p) | Operand::Move(p) => {
264+
VarDebugInfoContents::Place(CompoundPlace::from_place(p, self.tcx))
265+
}
264266
};
265267
let dbginfo = VarDebugInfo {
266268
name,

compiler/rustc_mir_build/src/builder/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -840,9 +840,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
840840
let Some(closure_arg) = self.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) else { return };
841841

842842
let mut closure_ty = closure_arg.ty;
843-
let mut closure_env_projs = vec![];
843+
let mut closure_env_projs: &[_] = &[];
844844
if let ty::Ref(_, ty, _) = closure_ty.kind() {
845-
closure_env_projs.push(ProjectionElem::Deref);
845+
closure_env_projs = &[ProjectionElem::Deref];
846846
closure_ty = *ty;
847847
}
848848

@@ -881,7 +881,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
881881

882882
let mutability = captured_place.mutability;
883883

884-
let mut projs = closure_env_projs.clone();
884+
let mut projs = closure_env_projs.to_vec();
885885
projs.push(ProjectionElem::Field(FieldIdx::new(i), ty));
886886
match capture {
887887
ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => {}
@@ -897,7 +897,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
897897
self.var_debug_info.push(VarDebugInfo {
898898
name,
899899
source_info: SourceInfo::outermost(captured_place.var_ident.span),
900-
value: VarDebugInfoContents::Place(use_place),
900+
value: VarDebugInfoContents::Place(CompoundPlace::from_place(use_place, tcx)),
901901
composite: None,
902902
argument_index: None,
903903
});

compiler/rustc_mir_transform/src/coroutine.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,29 @@ impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> {
158158
}
159159
}
160160
}
161-
}
162161

163-
fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
164-
place.local = new_base.local;
162+
fn visit_compound_place(
163+
&mut self,
164+
place: &mut CompoundPlace<'tcx>,
165+
context: PlaceContext,
166+
location: Location,
167+
) {
168+
if place.local == SELF_ARG {
169+
place.replace_local_with_place(self.new_base, self.tcx);
170+
} else {
171+
self.visit_local(&mut place.local, context, location);
165172

166-
let mut new_projection = new_base.projection.to_vec();
167-
new_projection.append(&mut place.projection.to_vec());
173+
for elem in place.projection_chain.iter().flatten() {
174+
if let PlaceElem::Index(local) = elem {
175+
assert_ne!(local, SELF_ARG);
176+
}
177+
}
178+
}
179+
}
180+
}
168181

169-
place.projection = tcx.mk_place_elems(&new_projection);
182+
fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtxt<'tcx>) {
183+
*place = new_base.project_deeper(place.projection, tcx);
170184
}
171185

172186
const SELF_ARG: Local = Local::from_u32(1);
@@ -406,6 +420,18 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
406420
}
407421
}
408422

423+
fn visit_compound_place(
424+
&mut self,
425+
place: &mut CompoundPlace<'tcx>,
426+
_context: PlaceContext,
427+
_location: Location,
428+
) {
429+
// Replace an Local in the remap with a coroutine struct access
430+
if let Some(&Some((ty, variant_index, idx))) = self.remap.get(place.local) {
431+
place.replace_local_with_place(self.make_field(variant_index, idx, ty), self.tcx);
432+
}
433+
}
434+
409435
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
410436
// Remove StorageLive and StorageDead statements for remapped locals
411437
for s in &mut data.statements {
@@ -1693,14 +1719,11 @@ impl EnsureCoroutineFieldAssignmentsNeverAlias<'_> {
16931719
}
16941720

16951721
impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> {
1696-
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
1722+
fn visit_place(&mut self, place: &Place<'tcx>, _context: PlaceContext, location: Location) {
16971723
let Some(lhs) = self.assigned_local else {
16981724
// This visitor only invokes `visit_place` for the right-hand side of an assignment
1699-
// and only after setting `self.assigned_local`. However, the default impl of
1700-
// `Visitor::super_body` may call `visit_place` with a `NonUseContext` for places
1701-
// with debuginfo. Ignore them here.
1702-
assert!(!context.is_use());
1703-
return;
1725+
// and only after setting `self.assigned_local`.
1726+
bug!()
17041727
};
17051728

17061729
let Some(rhs) = self.saved_local_for_direct_place(*place) else { return };

0 commit comments

Comments
 (0)