@@ -1226,30 +1226,50 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
12261226
12271227/// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
12281228fn is_discr_reassigned ( bcx : Block , discr : & ast:: Expr , body : & ast:: Expr ) -> bool {
1229- match discr. node {
1229+ let ( vid , field ) = match discr. node {
12301230 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 ) ) )
12431247 } ,
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) ;
12451259 }
1260+ rc. reassigned
12461261}
12471262
12481263struct ReassignmentChecker {
12491264 node : ast:: NodeId ,
1265+ field : Option < mc:: FieldName > ,
12501266 reassigned : bool
12511267}
12521268
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.
12531273impl < ' tcx > euv:: Delegate < ' tcx > for ReassignmentChecker {
12541274 fn consume ( & mut self , _: ast:: NodeId , _: Span , _: mc:: cmt , _: euv:: ConsumeMode ) { }
12551275 fn matched_pat ( & mut self , _: & ast:: Pat , _: mc:: cmt , _: euv:: MatchMode ) { }
@@ -1262,6 +1282,15 @@ impl<'tcx> euv::Delegate<'tcx> for ReassignmentChecker {
12621282 match cmt. cat {
12631283 mc:: cat_upvar( mc:: Upvar { id : ty:: UpvarId { var_id : vid, .. } , .. } ) |
12641284 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+ } ,
12651294 _ => { }
12661295 }
12671296 }
0 commit comments