@@ -547,7 +547,10 @@ impl<'tcx> Visitor<'tcx> for UsedLocals {
547
547
}
548
548
549
549
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 ( ) {
551
554
return ;
552
555
}
553
556
@@ -568,10 +571,9 @@ fn remove_unused_definitions_helper(used_locals: &mut UsedLocals, body: &mut Bod
568
571
569
572
if !used_locals. preserve_debug {
570
573
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) {
572
575
used_locals. is_used ( local)
573
576
} else {
574
- // Keep non-simple debuginfo no matter what
575
577
true
576
578
} ;
577
579
@@ -640,8 +642,27 @@ fn preserve_debug_even_if_never_generated(opts: &Options) -> bool {
640
642
}
641
643
}
642
644
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
+ }
647
668
}
0 commit comments