@@ -1226,30 +1226,50 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1226
1226
1227
1227
/// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
1228
1228
fn is_discr_reassigned ( bcx : Block , discr : & ast:: Expr , body : & ast:: Expr ) -> bool {
1229
- match discr. node {
1229
+ let ( vid , field ) = match discr. node {
1230
1230
ast:: ExprPath ( ..) => match bcx. def ( discr. id ) {
1231
- def:: DefLocal ( vid) | def:: DefUpvar ( vid, _, _) => {
1232
- let mut rc = ReassignmentChecker {
1233
- node : vid,
1234
- reassigned : false
1235
- } ;
1236
- {
1237
- let mut visitor = euv:: ExprUseVisitor :: new ( & mut rc, bcx) ;
1238
- visitor. walk_expr ( body) ;
1239
- }
1240
- rc. reassigned
1241
- }
1242
- _ => false
1231
+ def:: DefLocal ( vid) | def:: DefUpvar ( vid, _, _) => ( vid, None ) ,
1232
+ _ => return false
1233
+ } ,
1234
+ ast:: ExprField ( ref base, field) => {
1235
+ let vid = match bcx. tcx ( ) . def_map . borrow ( ) . get ( & base. id ) {
1236
+ Some ( & def:: DefLocal ( vid) ) | Some ( & def:: DefUpvar ( vid, _, _) ) => vid,
1237
+ _ => return false
1238
+ } ;
1239
+ ( vid, Some ( mc:: NamedField ( field. node . name ) ) )
1240
+ } ,
1241
+ ast:: ExprTupField ( ref base, field) => {
1242
+ let vid = match bcx. tcx ( ) . def_map . borrow ( ) . get ( & base. id ) {
1243
+ Some ( & def:: DefLocal ( vid) ) | Some ( & def:: DefUpvar ( vid, _, _) ) => vid,
1244
+ _ => return false
1245
+ } ;
1246
+ ( vid, Some ( mc:: PositionalField ( field. node ) ) )
1243
1247
} ,
1244
- _ => false
1248
+ _ => return false
1249
+ } ;
1250
+
1251
+ let mut rc = ReassignmentChecker {
1252
+ node : vid,
1253
+ field : field,
1254
+ reassigned : false
1255
+ } ;
1256
+ {
1257
+ let mut visitor = euv:: ExprUseVisitor :: new ( & mut rc, bcx) ;
1258
+ visitor. walk_expr ( body) ;
1245
1259
}
1260
+ rc. reassigned
1246
1261
}
1247
1262
1248
1263
struct ReassignmentChecker {
1249
1264
node : ast:: NodeId ,
1265
+ field : Option < mc:: FieldName > ,
1250
1266
reassigned : bool
1251
1267
}
1252
1268
1269
+ // Determine if the expression we're matching on is reassigned to within
1270
+ // the body of the match's arm.
1271
+ // We only care for the `mutate` callback since this check only matters
1272
+ // for cases where the matched value is moved.
1253
1273
impl < ' tcx > euv:: Delegate < ' tcx > for ReassignmentChecker {
1254
1274
fn consume ( & mut self , _: ast:: NodeId , _: Span , _: mc:: cmt , _: euv:: ConsumeMode ) { }
1255
1275
fn matched_pat ( & mut self , _: & ast:: Pat , _: mc:: cmt , _: euv:: MatchMode ) { }
@@ -1262,6 +1282,15 @@ impl<'tcx> euv::Delegate<'tcx> for ReassignmentChecker {
1262
1282
match cmt. cat {
1263
1283
mc:: cat_upvar( mc:: Upvar { id : ty:: UpvarId { var_id : vid, .. } , .. } ) |
1264
1284
mc:: cat_local( vid) => self . reassigned = self . node == vid,
1285
+ mc:: cat_interior( ref base_cmt, mc:: InteriorField ( field) ) => {
1286
+ match base_cmt. cat {
1287
+ mc:: cat_upvar( mc:: Upvar { id : ty:: UpvarId { var_id : vid, .. } , .. } ) |
1288
+ mc:: cat_local( vid) => {
1289
+ self . reassigned = self . node == vid && Some ( field) == self . field
1290
+ } ,
1291
+ _ => { }
1292
+ }
1293
+ } ,
1265
1294
_ => { }
1266
1295
}
1267
1296
}
0 commit comments