@@ -21,7 +21,8 @@ use rustc::middle::dataflow::DataFlowOperator;
21
21
use rustc:: middle:: dataflow:: KillFrom ;
22
22
use rustc:: middle:: expr_use_visitor as euv;
23
23
use rustc:: middle:: expr_use_visitor:: MutateMode ;
24
- use rustc:: ty:: TyCtxt ;
24
+ use rustc:: middle:: mem_categorization as mc;
25
+ use rustc:: ty:: { self , TyCtxt } ;
25
26
use rustc:: util:: nodemap:: { FnvHashMap , NodeSet } ;
26
27
27
28
use std:: cell:: RefCell ;
@@ -364,6 +365,32 @@ impl<'a, 'tcx> MoveData<'tcx> {
364
365
lp : Rc < LoanPath < ' tcx > > ,
365
366
id : ast:: NodeId ,
366
367
kind : MoveKind ) {
368
+ // Moving one union field automatically moves all its fields.
369
+ if let LpExtend ( ref base_lp, mutbl, LpInterior ( opt_variant_id, interior) ) = lp. kind {
370
+ if let ty:: TyUnion ( ref adt_def, _) = base_lp. ty . sty {
371
+ for field in & adt_def. struct_variant ( ) . fields {
372
+ let field = InteriorKind :: InteriorField ( mc:: NamedField ( field. name ) ) ;
373
+ let field_ty = if field == interior {
374
+ lp. ty
375
+ } else {
376
+ tcx. types . err // Doesn't matter
377
+ } ;
378
+ let sibling_lp_kind = LpExtend ( base_lp. clone ( ) , mutbl,
379
+ LpInterior ( opt_variant_id, field) ) ;
380
+ let sibling_lp = Rc :: new ( LoanPath :: new ( sibling_lp_kind, field_ty) ) ;
381
+ self . add_move_helper ( tcx, sibling_lp, id, kind) ;
382
+ }
383
+ return ;
384
+ }
385
+ }
386
+
387
+ self . add_move_helper ( tcx, lp. clone ( ) , id, kind) ;
388
+ }
389
+
390
+ fn add_move_helper ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
391
+ lp : Rc < LoanPath < ' tcx > > ,
392
+ id : ast:: NodeId ,
393
+ kind : MoveKind ) {
367
394
debug ! ( "add_move(lp={:?}, id={}, kind={:?})" ,
368
395
lp,
369
396
id,
@@ -393,6 +420,34 @@ impl<'a, 'tcx> MoveData<'tcx> {
393
420
span : Span ,
394
421
assignee_id : ast:: NodeId ,
395
422
mode : euv:: MutateMode ) {
423
+ // Assigning to one union field automatically assigns to all its fields.
424
+ if let LpExtend ( ref base_lp, mutbl, LpInterior ( opt_variant_id, interior) ) = lp. kind {
425
+ if let ty:: TyUnion ( ref adt_def, _) = base_lp. ty . sty {
426
+ for field in & adt_def. struct_variant ( ) . fields {
427
+ let field = InteriorKind :: InteriorField ( mc:: NamedField ( field. name ) ) ;
428
+ let field_ty = if field == interior {
429
+ lp. ty
430
+ } else {
431
+ tcx. types . err // Doesn't matter
432
+ } ;
433
+ let sibling_lp_kind = LpExtend ( base_lp. clone ( ) , mutbl,
434
+ LpInterior ( opt_variant_id, field) ) ;
435
+ let sibling_lp = Rc :: new ( LoanPath :: new ( sibling_lp_kind, field_ty) ) ;
436
+ self . add_assignment_helper ( tcx, sibling_lp, assign_id, span, assignee_id, mode) ;
437
+ }
438
+ return ;
439
+ }
440
+ }
441
+
442
+ self . add_assignment_helper ( tcx, lp. clone ( ) , assign_id, span, assignee_id, mode) ;
443
+ }
444
+
445
+ pub fn add_assignment_helper ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
446
+ lp : Rc < LoanPath < ' tcx > > ,
447
+ assign_id : ast:: NodeId ,
448
+ span : Span ,
449
+ assignee_id : ast:: NodeId ,
450
+ mode : euv:: MutateMode ) {
396
451
debug ! ( "add_assignment(lp={:?}, assign_id={}, assignee_id={}" ,
397
452
lp, assign_id, assignee_id) ;
398
453
0 commit comments