@@ -25,6 +25,7 @@ use middle::dataflow::DataFlowContext;
25
25
use middle:: dataflow:: BitwiseOperator ;
26
26
use middle:: dataflow:: DataFlowOperator ;
27
27
use euv = middle:: expr_use_visitor;
28
+ use mc = middle:: mem_categorization;
28
29
use middle:: ty;
29
30
use syntax:: ast;
30
31
use syntax:: ast_util;
@@ -160,6 +161,22 @@ pub struct AssignDataFlowOperator;
160
161
161
162
pub type AssignDataFlow < ' a > = DataFlowContext < ' a , AssignDataFlowOperator > ;
162
163
164
+ fn loan_path_is_precise ( loan_path : & LoanPath ) -> bool {
165
+ match * loan_path {
166
+ LpVar ( _) => {
167
+ true
168
+ }
169
+ LpExtend ( _, _, LpInterior ( mc:: InteriorElement ( _) ) ) => {
170
+ // Paths involving element accesses do not refer to a unique
171
+ // location, as there is no accurate tracking of the indices.
172
+ false
173
+ }
174
+ LpExtend ( ref lp_base, _, _) => {
175
+ loan_path_is_precise ( & * * lp_base)
176
+ }
177
+ }
178
+ }
179
+
163
180
impl MoveData {
164
181
pub fn new ( ) -> MoveData {
165
182
MoveData {
@@ -500,10 +517,17 @@ impl MoveData {
500
517
path : MovePathIndex ,
501
518
kill_id : ast:: NodeId ,
502
519
dfcx_moves : & mut MoveDataFlow ) {
503
- self . each_applicable_move ( path, |move_index| {
504
- dfcx_moves. add_kill ( kill_id, move_index. get ( ) ) ;
505
- true
506
- } ) ;
520
+ // We can only perform kills for paths that refer to a unique location,
521
+ // since otherwise we may kill a move from one location with an
522
+ // assignment referring to another location.
523
+
524
+ let loan_path = self . path_loan_path ( path) ;
525
+ if loan_path_is_precise ( & * loan_path) {
526
+ self . each_applicable_move ( path, |move_index| {
527
+ dfcx_moves. add_kill ( kill_id, move_index. get ( ) ) ;
528
+ true
529
+ } ) ;
530
+ }
507
531
}
508
532
}
509
533
0 commit comments