1
1
pub use super :: * ;
2
2
3
+ use crate :: dataflow:: generic:: { Results , ResultsRefCursor } ;
3
4
use crate :: dataflow:: BitDenotation ;
4
- use crate :: dataflow:: HaveBeenBorrowedLocals ;
5
- use crate :: dataflow:: { DataflowResults , DataflowResultsCursor , DataflowResultsRefCursor } ;
5
+ use crate :: dataflow:: MaybeBorrowedLocals ;
6
6
use rustc:: mir:: visit:: { NonMutatingUseContext , PlaceContext , Visitor } ;
7
7
use rustc:: mir:: * ;
8
8
use std:: cell:: RefCell ;
@@ -69,22 +69,23 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
69
69
const BOTTOM_VALUE : bool = false ;
70
70
}
71
71
72
+ type BorrowedLocalsResults < ' a , ' tcx > = ResultsRefCursor < ' a , ' a , ' tcx , MaybeBorrowedLocals > ;
73
+
72
74
/// Dataflow analysis that determines whether each local requires storage at a
73
75
/// given location; i.e. whether its storage can go away without being observed.
74
76
pub struct RequiresStorage < ' mir , ' tcx > {
75
77
body : ReadOnlyBodyAndCache < ' mir , ' tcx > ,
76
- borrowed_locals :
77
- RefCell < DataflowResultsRefCursor < ' mir , ' tcx , HaveBeenBorrowedLocals < ' mir , ' tcx > > > ,
78
+ borrowed_locals : RefCell < BorrowedLocalsResults < ' mir , ' tcx > > ,
78
79
}
79
80
80
81
impl < ' mir , ' tcx : ' mir > RequiresStorage < ' mir , ' tcx > {
81
82
pub fn new (
82
83
body : ReadOnlyBodyAndCache < ' mir , ' tcx > ,
83
- borrowed_locals : & ' mir DataflowResults < ' tcx , HaveBeenBorrowedLocals < ' mir , ' tcx > > ,
84
+ borrowed_locals : & ' mir Results < ' tcx , MaybeBorrowedLocals > ,
84
85
) -> Self {
85
86
RequiresStorage {
86
87
body,
87
- borrowed_locals : RefCell :: new ( DataflowResultsCursor :: new ( borrowed_locals , * body) ) ,
88
+ borrowed_locals : RefCell :: new ( ResultsRefCursor :: new ( * body, borrowed_locals ) ) ,
88
89
}
89
90
}
90
91
@@ -111,11 +112,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
111
112
}
112
113
113
114
fn before_statement_effect ( & self , sets : & mut GenKillSet < Self :: Idx > , loc : Location ) {
114
- // If we borrow or assign to a place then it needs storage for that
115
- // statement.
116
- self . check_for_borrow ( sets, loc) ;
117
-
118
115
let stmt = & self . body [ loc. block ] . statements [ loc. statement_index ] ;
116
+
117
+ // If a place is borrowed in a statement, it needs storage for that statement.
118
+ self . borrowed_locals . borrow ( ) . analysis ( ) . statement_effect ( sets, stmt, loc) ;
119
+
120
+ // If a place is assigned to in a statement, it needs storage for that statement.
119
121
match stmt. kind {
120
122
StatementKind :: StorageDead ( l) => sets. kill ( l) ,
121
123
StatementKind :: Assign ( box ( ref place, _) )
@@ -138,12 +140,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
138
140
}
139
141
140
142
fn before_terminator_effect ( & self , sets : & mut GenKillSet < Local > , loc : Location ) {
141
- self . check_for_borrow ( sets , loc) ;
143
+ let terminator = self . body [ loc. block ] . terminator ( ) ;
142
144
143
- if let TerminatorKind :: Call { destination : Some ( ( Place { local, .. } , _) ) , .. } =
144
- self . body [ loc. block ] . terminator ( ) . kind
145
- {
146
- sets. gen ( local) ;
145
+ // If a place is borrowed in a terminator, it needs storage for that terminator.
146
+ self . borrowed_locals . borrow ( ) . analysis ( ) . terminator_effect ( sets, terminator, loc) ;
147
+
148
+ if let TerminatorKind :: Call { destination : Some ( ( place, _) ) , .. } = terminator. kind {
149
+ sets. gen ( place. local ) ;
147
150
}
148
151
}
149
152
@@ -179,14 +182,6 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
179
182
let mut visitor = MoveVisitor { sets, borrowed_locals : & self . borrowed_locals } ;
180
183
visitor. visit_location ( self . body , loc) ;
181
184
}
182
-
183
- /// Gen locals that are newly borrowed. This includes borrowing any part of
184
- /// a local (we rely on this behavior of `HaveBeenBorrowedLocals`).
185
- fn check_for_borrow ( & self , sets : & mut GenKillSet < Local > , loc : Location ) {
186
- let mut borrowed_locals = self . borrowed_locals . borrow_mut ( ) ;
187
- borrowed_locals. seek ( loc) ;
188
- borrowed_locals. each_gen_bit ( |l| sets. gen ( l) ) ;
189
- }
190
185
}
191
186
192
187
impl < ' mir , ' tcx > BottomValue for RequiresStorage < ' mir , ' tcx > {
@@ -195,16 +190,15 @@ impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
195
190
}
196
191
197
192
struct MoveVisitor < ' a , ' mir , ' tcx > {
198
- borrowed_locals :
199
- & ' a RefCell < DataflowResultsRefCursor < ' mir , ' tcx , HaveBeenBorrowedLocals < ' mir , ' tcx > > > ,
193
+ borrowed_locals : & ' a RefCell < BorrowedLocalsResults < ' mir , ' tcx > > ,
200
194
sets : & ' a mut GenKillSet < Local > ,
201
195
}
202
196
203
197
impl < ' a , ' mir : ' a , ' tcx > Visitor < ' tcx > for MoveVisitor < ' a , ' mir , ' tcx > {
204
198
fn visit_local ( & mut self , local : & Local , context : PlaceContext , loc : Location ) {
205
199
if PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move ) == context {
206
200
let mut borrowed_locals = self . borrowed_locals . borrow_mut ( ) ;
207
- borrowed_locals. seek ( loc) ;
201
+ borrowed_locals. seek_before ( loc) ;
208
202
if !borrowed_locals. contains ( * local) {
209
203
self . sets . kill ( * local) ;
210
204
}
0 commit comments