@@ -18,13 +18,24 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
18
18
. iterate_to_fixpoint ( )
19
19
. into_results_cursor ( body) ;
20
20
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) ;
22
31
}
23
32
24
33
struct Lint < ' a , ' tcx > {
25
34
tcx : TyCtxt < ' tcx > ,
26
35
when : String ,
27
36
body : & ' a Body < ' tcx > ,
37
+ is_fn_like : bool ,
38
+ always_live_locals : & ' a BitSet < Local > ,
28
39
reachable_blocks : BitSet < BasicBlock > ,
29
40
storage_liveness : ResultsCursor < ' a , ' tcx , MaybeStorageLive < ' a > > ,
30
41
}
@@ -74,4 +85,27 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
74
85
75
86
self . super_statement ( statement, location) ;
76
87
}
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
+ }
77
111
}
0 commit comments