11use rustc_index:: bit_set:: BitSet ;
2- use rustc_middle:: mir:: { self , Local } ;
2+ use rustc_middle:: mir:: visit:: Visitor ;
3+ use rustc_middle:: mir:: { self , Local , Location } ;
34
45/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations.
56///
@@ -12,20 +13,12 @@ pub struct AlwaysLiveLocals(BitSet<Local>);
1213
1314impl AlwaysLiveLocals {
1415 pub fn new ( body : & mir:: Body < ' tcx > ) -> Self {
15- let mut locals = BitSet :: new_filled ( body. local_decls . len ( ) ) ;
16-
17- // FIXME: Use a visitor for this when `visit_body` can take a plain `Body`.
18- for block in body. basic_blocks ( ) . iter ( ) {
19- for stmt in & block. statements {
20- if let mir:: StatementKind :: StorageLive ( l) | mir:: StatementKind :: StorageDead ( l) =
21- stmt. kind
22- {
23- locals. remove ( l) ;
24- }
25- }
26- }
16+ let mut ret = AlwaysLiveLocals ( BitSet :: new_filled ( body. local_decls . len ( ) ) ) ;
17+
18+ let mut vis = StorageAnnotationVisitor ( & mut ret) ;
19+ vis. visit_body ( body) ;
2720
28- AlwaysLiveLocals ( locals )
21+ ret
2922 }
3023
3124 pub fn into_inner ( self ) -> BitSet < Local > {
@@ -40,3 +33,15 @@ impl std::ops::Deref for AlwaysLiveLocals {
4033 & self . 0
4134 }
4235}
36+
37+ /// Removes locals that have `Storage*` annotations from `AlwaysLiveLocals`.
38+ struct StorageAnnotationVisitor < ' a > ( & ' a mut AlwaysLiveLocals ) ;
39+
40+ impl Visitor < ' tcx > for StorageAnnotationVisitor < ' _ > {
41+ fn visit_statement ( & mut self , statement : & mir:: Statement < ' tcx > , _location : Location ) {
42+ use mir:: StatementKind :: { StorageDead , StorageLive } ;
43+ if let StorageLive ( l) | StorageDead ( l) = statement. kind {
44+ ( self . 0 ) . 0 . remove ( l) ;
45+ }
46+ }
47+ }
0 commit comments