@@ -17,6 +17,7 @@ use rustc_middle::ty::{
1717    self ,  CoroutineArgsExt ,  InstanceKind ,  ScalarInt ,  Ty ,  TyCtxt ,  TypeVisitableExt ,  Upcast ,  Variance , 
1818} ; 
1919use  rustc_middle:: { bug,  span_bug} ; 
20+ use  rustc_mir_dataflow:: debuginfo:: debuginfo_locals; 
2021use  rustc_trait_selection:: traits:: ObligationCtxt ; 
2122
2223use  crate :: util:: { self ,  is_within_packed} ; 
@@ -80,6 +81,11 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
8081            cfg_checker. fail ( location,  msg) ; 
8182        } 
8283
84+         // Ensure that debuginfo records are not emitted for locals that are not in debuginfo. 
85+         for  ( location,  msg)  in  validate_debuginfos ( body)  { 
86+             cfg_checker. fail ( location,  msg) ; 
87+         } 
88+ 
8389        if  let  MirPhase :: Runtime ( _)  = body. phase 
8490            && let  ty:: InstanceKind :: Item ( _)  = body. source . instance 
8591            && body. has_free_regions ( ) 
@@ -1595,3 +1601,30 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15951601        self . super_terminator ( terminator,  location) ; 
15961602    } 
15971603} 
1604+ 
1605+ pub ( super )  fn  validate_debuginfos < ' tcx > ( body :  & Body < ' tcx > )  -> Vec < ( Location ,  String ) >  { 
1606+     let  mut  debuginfo_checker =
1607+         DebuginfoChecker  {  debuginfo_locals :  debuginfo_locals ( body) ,  failures :  Vec :: new ( )  } ; 
1608+     debuginfo_checker. visit_body ( body) ; 
1609+     debuginfo_checker. failures 
1610+ } 
1611+ 
1612+ struct  DebuginfoChecker  { 
1613+     debuginfo_locals :  DenseBitSet < Local > , 
1614+     failures :  Vec < ( Location ,  String ) > , 
1615+ } 
1616+ 
1617+ impl < ' tcx >  Visitor < ' tcx >  for  DebuginfoChecker  { 
1618+     fn  visit_statement_debuginfo ( 
1619+         & mut  self , 
1620+         stmt_debuginfo :  & StmtDebugInfo < ' tcx > , 
1621+         location :  Location , 
1622+     )  { 
1623+         let  local = match  stmt_debuginfo { 
1624+             StmtDebugInfo :: AssignRef ( local,  _)  | StmtDebugInfo :: InvalidAssign ( local)  => * local, 
1625+         } ; 
1626+         if  !self . debuginfo_locals . contains ( local)  { 
1627+             self . failures . push ( ( location,  format ! ( "{local:?} is not in debuginfo" ) ) ) ; 
1628+         } 
1629+     } 
1630+ } 
0 commit comments