@@ -18,13 +18,24 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
1818 . iterate_to_fixpoint ( )
1919 . into_results_cursor ( body) ;
2020
21- Lint { tcx, when, body, reachable_blocks, storage_liveness } . visit_body ( body) ;
21+ Lint {
22+ tcx,
23+ when,
24+ body,
25+ is_fn_like : tcx. def_kind ( body. source . def_id ( ) ) . is_fn_like ( ) ,
26+ always_live_locals,
27+ reachable_blocks,
28+ storage_liveness,
29+ }
30+ . visit_body ( body) ;
2231}
2332
2433struct Lint < ' a , ' tcx > {
2534 tcx : TyCtxt < ' tcx > ,
2635 when : String ,
2736 body : & ' a Body < ' tcx > ,
37+ is_fn_like : bool ,
38+ always_live_locals : & ' a BitSet < Local > ,
2839 reachable_blocks : BitSet < BasicBlock > ,
2940 storage_liveness : ResultsCursor < ' a , ' tcx , MaybeStorageLive < ' a > > ,
3041}
@@ -74,4 +85,27 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
7485
7586 self . super_statement ( statement, location) ;
7687 }
88+
89+ fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
90+ match terminator. kind {
91+ TerminatorKind :: Return => {
92+ if self . is_fn_like && self . reachable_blocks . contains ( location. block ) {
93+ self . storage_liveness . seek_after_primary_effect ( location) ;
94+ for local in self . storage_liveness . get ( ) . iter ( ) {
95+ if !self . always_live_locals . contains ( local) {
96+ self . fail (
97+ location,
98+ format ! (
99+ "local {local:?} still has storage when returning from function"
100+ ) ,
101+ ) ;
102+ }
103+ }
104+ }
105+ }
106+ _ => { }
107+ }
108+
109+ self . super_terminator ( terminator, location) ;
110+ }
77111}
0 commit comments