@@ -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,23 @@ 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 { Some ( local) } else { None }
647664}
0 commit comments