@@ -30,9 +30,10 @@ use dataflow::{do_dataflow};
30
30
use dataflow:: { MoveDataParamEnv } ;
31
31
use dataflow:: { BitDenotation , BlockSets , DataflowResults , DataflowResultsConsumer } ;
32
32
use dataflow:: { MaybeInitializedLvals , MaybeUninitializedLvals } ;
33
+ use dataflow:: { MovingOutStatements } ;
33
34
use dataflow:: { Borrows , BorrowData , BorrowIndex } ;
34
35
use dataflow:: move_paths:: { MoveError , IllegalMoveOriginKind } ;
35
- use dataflow:: move_paths:: { HasMoveData , MoveData , MovePathIndex , LookupResult } ;
36
+ use dataflow:: move_paths:: { HasMoveData , MoveData , MovePathIndex , LookupResult , MoveOutIndex } ;
36
37
use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
37
38
38
39
use self :: MutateMode :: { JustWrite , WriteAndRead } ;
@@ -129,6 +130,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
129
130
let flow_uninits = do_dataflow ( tcx, mir, id, & attributes, & dead_unwinds,
130
131
MaybeUninitializedLvals :: new ( tcx, mir, & mdpe) ,
131
132
|bd, i| & bd. move_data ( ) . move_paths [ i] ) ;
133
+ let flow_move_outs = do_dataflow ( tcx, mir, id, & attributes, & dead_unwinds,
134
+ MovingOutStatements :: new ( tcx, mir, & mdpe) ,
135
+ |bd, i| & bd. move_data ( ) . moves [ i] ) ;
132
136
133
137
let mut mbcx = MirBorrowckCtxt {
134
138
tcx : tcx,
@@ -141,7 +145,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
141
145
142
146
let mut state = InProgress :: new ( flow_borrows,
143
147
flow_inits,
144
- flow_uninits) ;
148
+ flow_uninits,
149
+ flow_move_outs) ;
145
150
146
151
mbcx. analyze_results ( & mut state) ; // entry point for DataflowResultsConsumer
147
152
}
@@ -161,6 +166,7 @@ pub struct InProgress<'b, 'gcx: 'tcx, 'tcx: 'b> {
161
166
borrows : FlowInProgress < Borrows < ' b , ' gcx , ' tcx > > ,
162
167
inits : FlowInProgress < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ,
163
168
uninits : FlowInProgress < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ,
169
+ move_outs : FlowInProgress < MovingOutStatements < ' b , ' gcx , ' tcx > > ,
164
170
}
165
171
166
172
struct FlowInProgress < BD > where BD : BitDenotation {
@@ -185,31 +191,35 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'tcx>
185
191
fn reset_to_entry_of ( & mut self , bb : BasicBlock , flow_state : & mut Self :: FlowState ) {
186
192
flow_state. each_flow ( |b| b. reset_to_entry_of ( bb) ,
187
193
|i| i. reset_to_entry_of ( bb) ,
188
- |u| u. reset_to_entry_of ( bb) ) ;
194
+ |u| u. reset_to_entry_of ( bb) ,
195
+ |m| m. reset_to_entry_of ( bb) ) ;
189
196
}
190
197
191
198
fn reconstruct_statement_effect ( & mut self ,
192
199
location : Location ,
193
200
flow_state : & mut Self :: FlowState ) {
194
201
flow_state. each_flow ( |b| b. reconstruct_statement_effect ( location) ,
195
202
|i| i. reconstruct_statement_effect ( location) ,
196
- |u| u. reconstruct_statement_effect ( location) ) ;
203
+ |u| u. reconstruct_statement_effect ( location) ,
204
+ |m| m. reconstruct_statement_effect ( location) ) ;
197
205
}
198
206
199
207
fn apply_local_effect ( & mut self ,
200
208
_location : Location ,
201
209
flow_state : & mut Self :: FlowState ) {
202
210
flow_state. each_flow ( |b| b. apply_local_effect ( ) ,
203
211
|i| i. apply_local_effect ( ) ,
204
- |u| u. apply_local_effect ( ) ) ;
212
+ |u| u. apply_local_effect ( ) ,
213
+ |m| m. apply_local_effect ( ) ) ;
205
214
}
206
215
207
216
fn reconstruct_terminator_effect ( & mut self ,
208
217
location : Location ,
209
218
flow_state : & mut Self :: FlowState ) {
210
219
flow_state. each_flow ( |b| b. reconstruct_terminator_effect ( location) ,
211
220
|i| i. reconstruct_terminator_effect ( location) ,
212
- |u| u. reconstruct_terminator_effect ( location) ) ;
221
+ |u| u. reconstruct_terminator_effect ( location) ,
222
+ |m| m. reconstruct_terminator_effect ( location) ) ;
213
223
}
214
224
215
225
fn visit_block_entry ( & mut self ,
@@ -671,6 +681,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
671
681
let lvalue = self . base_path ( lvalue_span. 0 ) ;
672
682
673
683
let maybe_uninits = & flow_state. uninits ;
684
+ let curr_move_outs = & flow_state. move_outs . curr_state ;
674
685
675
686
// Bad scenarios:
676
687
//
@@ -712,7 +723,9 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
712
723
match self . move_path_closest_to ( lvalue) {
713
724
Ok ( mpi) => {
714
725
if maybe_uninits. curr_state . contains ( & mpi) {
715
- self . report_use_of_moved ( context, desired_action, lvalue_span) ;
726
+ self . report_use_of_moved_or_uninitialized ( context, desired_action,
727
+ lvalue_span, mpi,
728
+ curr_move_outs) ;
716
729
return ; // don't bother finding other problems.
717
730
}
718
731
}
@@ -737,8 +750,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
737
750
738
751
debug ! ( "check_if_path_is_moved part2 lvalue: {:?}" , lvalue) ;
739
752
if let Some ( mpi) = self . move_path_for_lvalue ( lvalue) {
740
- if let Some ( _) = maybe_uninits. has_any_child_of ( mpi) {
741
- self . report_use_of_moved ( context, desired_action, lvalue_span) ;
753
+ if let Some ( child_mpi) = maybe_uninits. has_any_child_of ( mpi) {
754
+ self . report_use_of_moved_or_uninitialized ( context, desired_action,
755
+ lvalue_span, child_mpi,
756
+ curr_move_outs) ;
742
757
return ; // don't bother finding other problems.
743
758
}
744
759
}
@@ -1083,17 +1098,47 @@ mod prefixes {
1083
1098
}
1084
1099
1085
1100
impl < ' c , ' b , ' a : ' b +' c , ' gcx , ' tcx : ' a > MirBorrowckCtxt < ' c , ' b , ' a , ' gcx , ' tcx > {
1086
- fn report_use_of_moved ( & mut self ,
1101
+ fn report_use_of_moved_or_uninitialized ( & mut self ,
1087
1102
_context : Context ,
1088
1103
desired_action : & str ,
1089
- ( lvalue, span) : ( & Lvalue , Span ) ) {
1090
- self . tcx . cannot_act_on_uninitialized_variable ( span,
1091
- desired_action,
1092
- & self . describe_lvalue ( lvalue) ,
1093
- Origin :: Mir )
1094
- . span_label ( span, format ! ( "use of possibly uninitialized `{}`" ,
1095
- self . describe_lvalue( lvalue) ) )
1096
- . emit ( ) ;
1104
+ ( lvalue, span) : ( & Lvalue , Span ) ,
1105
+ mpi : MovePathIndex ,
1106
+ curr_move_out : & IdxSetBuf < MoveOutIndex > ) {
1107
+
1108
+ let mois = self . move_data . path_map [ mpi] . iter ( ) . filter (
1109
+ |moi| curr_move_out. contains ( moi) ) . collect :: < Vec < _ > > ( ) ;
1110
+
1111
+ if mois. is_empty ( ) {
1112
+ self . tcx . cannot_act_on_uninitialized_variable ( span,
1113
+ desired_action,
1114
+ & self . describe_lvalue ( lvalue) ,
1115
+ Origin :: Mir )
1116
+ . span_label ( span, format ! ( "use of possibly uninitialized `{}`" ,
1117
+ self . describe_lvalue( lvalue) ) )
1118
+ . emit ( ) ;
1119
+ } else {
1120
+ let msg = "" ; //FIXME: add "partially " or "collaterally "
1121
+
1122
+ let mut err = self . tcx . cannot_act_on_moved_value ( span,
1123
+ desired_action,
1124
+ msg,
1125
+ & self . describe_lvalue ( lvalue) ,
1126
+ Origin :: Mir ) ;
1127
+ err. span_label ( span, format ! ( "value {} here after move" , desired_action) ) ;
1128
+ for moi in mois {
1129
+ let move_msg = "" ; //FIXME: add " (into closure)"
1130
+ let move_span = self . mir . source_info ( self . move_data . moves [ * moi] . source ) . span ;
1131
+ if span == move_span {
1132
+ err. span_label ( span,
1133
+ format ! ( "value moved{} here in previous iteration of loop" ,
1134
+ move_msg) ) ;
1135
+ } else {
1136
+ err. span_label ( move_span, format ! ( "value moved{} here" , move_msg) ) ;
1137
+ } ;
1138
+ }
1139
+ //FIXME: add note for closure
1140
+ err. emit ( ) ;
1141
+ }
1097
1142
}
1098
1143
1099
1144
fn report_move_out_while_borrowed ( & mut self ,
@@ -1396,26 +1441,31 @@ impl ContextKind {
1396
1441
impl < ' b , ' gcx , ' tcx > InProgress < ' b , ' gcx , ' tcx > {
1397
1442
pub ( super ) fn new ( borrows : DataflowResults < Borrows < ' b , ' gcx , ' tcx > > ,
1398
1443
inits : DataflowResults < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ,
1399
- uninits : DataflowResults < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > )
1444
+ uninits : DataflowResults < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ,
1445
+ move_out : DataflowResults < MovingOutStatements < ' b , ' gcx , ' tcx > > )
1400
1446
-> Self {
1401
1447
InProgress {
1402
1448
borrows : FlowInProgress :: new ( borrows) ,
1403
1449
inits : FlowInProgress :: new ( inits) ,
1404
1450
uninits : FlowInProgress :: new ( uninits) ,
1451
+ move_outs : FlowInProgress :: new ( move_out)
1405
1452
}
1406
1453
}
1407
1454
1408
- fn each_flow < XB , XI , XU > ( & mut self ,
1409
- mut xform_borrows : XB ,
1410
- mut xform_inits : XI ,
1411
- mut xform_uninits : XU ) where
1455
+ fn each_flow < XB , XI , XU , XM > ( & mut self ,
1456
+ mut xform_borrows : XB ,
1457
+ mut xform_inits : XI ,
1458
+ mut xform_uninits : XU ,
1459
+ mut xform_move_outs : XM ) where
1412
1460
XB : FnMut ( & mut FlowInProgress < Borrows < ' b , ' gcx , ' tcx > > ) ,
1413
1461
XI : FnMut ( & mut FlowInProgress < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ) ,
1414
1462
XU : FnMut ( & mut FlowInProgress < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ) ,
1463
+ XM : FnMut ( & mut FlowInProgress < MovingOutStatements < ' b , ' gcx , ' tcx > > ) ,
1415
1464
{
1416
1465
xform_borrows ( & mut self . borrows ) ;
1417
1466
xform_inits ( & mut self . inits ) ;
1418
1467
xform_uninits ( & mut self . uninits ) ;
1468
+ xform_move_outs ( & mut self . move_outs ) ;
1419
1469
}
1420
1470
1421
1471
fn summary ( & self ) -> String {
@@ -1461,6 +1511,17 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
1461
1511
& self . uninits . base_results . operator ( ) . move_data ( ) . move_paths [ mpi_uninit] ;
1462
1512
s. push_str ( & format ! ( "{}" , move_path) ) ;
1463
1513
} ) ;
1514
+ s. push_str ( "] " ) ;
1515
+
1516
+ s. push_str ( "move_out: [" ) ;
1517
+ let mut saw_one = false ;
1518
+ self . move_outs . each_state_bit ( |mpi_move_out| {
1519
+ if saw_one { s. push_str ( ", " ) ; } ;
1520
+ saw_one = true ;
1521
+ let move_out =
1522
+ & self . move_outs . base_results . operator ( ) . move_data ( ) . moves [ mpi_move_out] ;
1523
+ s. push_str ( & format ! ( "{:?}" , move_out) ) ;
1524
+ } ) ;
1464
1525
s. push_str ( "]" ) ;
1465
1526
1466
1527
return s;
0 commit comments