1
1
use 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 } ;
3
4
4
5
/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations.
5
6
///
@@ -12,20 +13,12 @@ pub struct AlwaysLiveLocals(BitSet<Local>);
12
13
13
14
impl AlwaysLiveLocals {
14
15
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) ;
27
20
28
- AlwaysLiveLocals ( locals )
21
+ ret
29
22
}
30
23
31
24
pub fn into_inner ( self ) -> BitSet < Local > {
@@ -40,3 +33,15 @@ impl std::ops::Deref for AlwaysLiveLocals {
40
33
& self . 0
41
34
}
42
35
}
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