Skip to content

Commit 4dfcb7d

Browse files
committed
Clarify the purpose of the single-Local check, and check it more flexibly
1 parent 83744cb commit 4dfcb7d

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

compiler/rustc_mir_transform/src/simplify.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,10 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
547547
}
548548

549549
fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
550-
if !self.preserve_debug && debug_info_is_for_simple_local(var_debug_info).is_some() {
550+
// We don't want to have to track *conditional* uses (such as
551+
// "`_4` is used iff `_5` is used" from `debug x => Foo(_4, _5)`),
552+
// so if this mentions multiple locals we just treat them all as used.
553+
if !self.preserve_debug && debug_info_is_for_single_local(var_debug_info).is_some() {
551554
return;
552555
}
553556

@@ -568,10 +571,9 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod
568571

569572
if !used_locals.preserve_debug {
570573
body.var_debug_info.retain(|info| {
571-
let keep = if let Some(local) = debug_info_is_for_simple_local(info) {
574+
let keep = if let Some(local) = debug_info_is_for_single_local(info) {
572575
used_locals.is_used(local)
573576
} else {
574-
// Keep non-simple debuginfo no matter what
575577
true
576578
};
577579

@@ -640,8 +642,27 @@ fn preserve_debug_even_if_never_generated(opts: &Options) -> bool {
640642
}
641643
}
642644

643-
// For now we only remove basic debuginfo, like `foo => _3`, and don't attempt
644-
// to clean up more complicated things like `foo => Foo { .0 => _2, .1 => _4 }`
645-
fn debug_info_is_for_simple_local(info: &VarDebugInfo<'_>) -> Option<Local> {
646-
if let VarDebugInfoContents::Place(place) = info.value { place.as_local() } else { None }
645+
/// Returns the only [`Local`] mentioned in `info`, if there's exactly one.
646+
/// Otherwise return `None` if this mentions no `Local`s (probably because
647+
/// it's [`VarDebugInfoContents::Const`]) or multiple `Local`s.
648+
fn debug_info_is_for_single_local(info: &VarDebugInfo<'_>) -> Option<Local> {
649+
struct SingleLocalFinder(Result<Option<Local>, ()>);
650+
impl Visitor<'_> for SingleLocalFinder {
651+
fn visit_local(&mut self, local: Local, _ctx: PlaceContext, _location: Location) {
652+
match &mut self.0 {
653+
Err(()) => {}
654+
Ok(opt @ None) => *opt = Some(local),
655+
Ok(Some(current)) if *current == local => {}
656+
res @ Ok(Some(_)) => *res = Err(()),
657+
}
658+
}
659+
}
660+
661+
let mut finder = SingleLocalFinder(Ok(None));
662+
finder.visit_var_debug_info(info);
663+
if let Ok(Some(local)) = finder.0 {
664+
Some(local)
665+
} else {
666+
None
667+
}
647668
}

0 commit comments

Comments
 (0)