@@ -150,6 +150,23 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
150
150
span. allows_unstable ( ) ;
151
151
}
152
152
}
153
+
154
+ /// While the `ExprUseVisitor` walks, we will identify which
155
+ /// expressions are borrowed, and insert their ids into this
156
+ /// table. Actually, we insert the "borrow-id", which is normally
157
+ /// the id of the expession being borrowed: but in the case of
158
+ /// `ref mut` borrows, the `id` of the pattern is
159
+ /// inserted. Therefore later we remove that entry from the table
160
+ /// and transfer it over to the value being matched. This will
161
+ /// then prevent said value from being promoted.
162
+ fn remove_mut_rvalue_borrow ( & mut self , pat : & hir:: Pat ) -> bool {
163
+ let mut any_removed = false ;
164
+ pat. walk ( |p| {
165
+ any_removed |= self . mut_rvalue_borrows . remove ( & p. id ) ;
166
+ true
167
+ } ) ;
168
+ any_removed
169
+ }
153
170
}
154
171
155
172
impl < ' a , ' tcx > Visitor < ' tcx > for CheckCrateVisitor < ' a , ' tcx > {
@@ -200,9 +217,15 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
200
217
fn visit_stmt ( & mut self , stmt : & ' tcx hir:: Stmt ) {
201
218
match stmt. node {
202
219
hir:: StmtDecl ( ref decl, _) => {
203
- match decl. node {
204
- hir:: DeclLocal ( _ ) => {
220
+ match & decl. node {
221
+ hir:: DeclLocal ( local ) => {
205
222
self . promotable = false ;
223
+
224
+ if self . remove_mut_rvalue_borrow ( & local. pat ) {
225
+ if let Some ( init) = & local. init {
226
+ self . mut_rvalue_borrows . insert ( init. id ) ;
227
+ }
228
+ }
206
229
}
207
230
// Item statements are allowed
208
231
hir:: DeclItem ( _) => { }
@@ -229,9 +252,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
229
252
// patterns and set that on the discriminator.
230
253
let mut mut_borrow = false ;
231
254
for pat in arms. iter ( ) . flat_map ( |arm| & arm. pats ) {
232
- if self . mut_rvalue_borrows . remove ( & pat. id ) {
233
- mut_borrow = true ;
234
- }
255
+ mut_borrow = self . remove_mut_rvalue_borrow ( pat) ;
235
256
}
236
257
if mut_borrow {
237
258
self . mut_rvalue_borrows . insert ( discr. id ) ;
@@ -498,6 +519,14 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
498
519
_loan_region : ty:: Region < ' tcx > ,
499
520
bk : ty:: BorrowKind ,
500
521
loan_cause : euv:: LoanCause ) {
522
+ debug ! (
523
+ "borrow(borrow_id={:?}, cmt={:?}, bk={:?}, loan_cause={:?})" ,
524
+ borrow_id,
525
+ cmt,
526
+ bk,
527
+ loan_cause,
528
+ ) ;
529
+
501
530
// Kind of hacky, but we allow Unsafe coercions in constants.
502
531
// These occur when we convert a &T or *T to a *U, as well as
503
532
// when making a thin pointer (e.g., `*T`) into a fat pointer
0 commit comments