@@ -30,9 +30,10 @@ use dataflow::{do_dataflow};
3030use dataflow:: { MoveDataParamEnv } ;
3131use dataflow:: { BitDenotation , BlockSets , DataflowResults , DataflowResultsConsumer } ;
3232use dataflow:: { MaybeInitializedLvals , MaybeUninitializedLvals } ;
33+ use dataflow:: { MovingOutStatements } ;
3334use dataflow:: { Borrows , BorrowData , BorrowIndex } ;
3435use dataflow:: move_paths:: { MoveError , IllegalMoveOriginKind } ;
35- use dataflow:: move_paths:: { HasMoveData , MoveData , MovePathIndex , LookupResult } ;
36+ use dataflow:: move_paths:: { HasMoveData , MoveData , MovePathIndex , LookupResult , MoveOutIndex } ;
3637use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
3738
3839use self :: MutateMode :: { JustWrite , WriteAndRead } ;
@@ -129,6 +130,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
129130 let flow_uninits = do_dataflow ( tcx, mir, id, & attributes, & dead_unwinds,
130131 MaybeUninitializedLvals :: new ( tcx, mir, & mdpe) ,
131132 |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] ) ;
132136
133137 let mut mbcx = MirBorrowckCtxt {
134138 tcx : tcx,
@@ -141,7 +145,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
141145
142146 let mut state = InProgress :: new ( flow_borrows,
143147 flow_inits,
144- flow_uninits) ;
148+ flow_uninits,
149+ flow_move_outs) ;
145150
146151 mbcx. analyze_results ( & mut state) ; // entry point for DataflowResultsConsumer
147152}
@@ -161,6 +166,7 @@ pub struct InProgress<'b, 'gcx: 'tcx, 'tcx: 'b> {
161166 borrows : FlowInProgress < Borrows < ' b , ' gcx , ' tcx > > ,
162167 inits : FlowInProgress < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ,
163168 uninits : FlowInProgress < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ,
169+ move_outs : FlowInProgress < MovingOutStatements < ' b , ' gcx , ' tcx > > ,
164170}
165171
166172struct FlowInProgress < BD > where BD : BitDenotation {
@@ -185,31 +191,35 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'tcx>
185191 fn reset_to_entry_of ( & mut self , bb : BasicBlock , flow_state : & mut Self :: FlowState ) {
186192 flow_state. each_flow ( |b| b. reset_to_entry_of ( bb) ,
187193 |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) ) ;
189196 }
190197
191198 fn reconstruct_statement_effect ( & mut self ,
192199 location : Location ,
193200 flow_state : & mut Self :: FlowState ) {
194201 flow_state. each_flow ( |b| b. reconstruct_statement_effect ( location) ,
195202 |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) ) ;
197205 }
198206
199207 fn apply_local_effect ( & mut self ,
200208 _location : Location ,
201209 flow_state : & mut Self :: FlowState ) {
202210 flow_state. each_flow ( |b| b. apply_local_effect ( ) ,
203211 |i| i. apply_local_effect ( ) ,
204- |u| u. apply_local_effect ( ) ) ;
212+ |u| u. apply_local_effect ( ) ,
213+ |m| m. apply_local_effect ( ) ) ;
205214 }
206215
207216 fn reconstruct_terminator_effect ( & mut self ,
208217 location : Location ,
209218 flow_state : & mut Self :: FlowState ) {
210219 flow_state. each_flow ( |b| b. reconstruct_terminator_effect ( location) ,
211220 |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) ) ;
213223 }
214224
215225 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>
671681 let lvalue = self . base_path ( lvalue_span. 0 ) ;
672682
673683 let maybe_uninits = & flow_state. uninits ;
684+ let curr_move_outs = & flow_state. move_outs . curr_state ;
674685
675686 // Bad scenarios:
676687 //
@@ -712,7 +723,9 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
712723 match self . move_path_closest_to ( lvalue) {
713724 Ok ( mpi) => {
714725 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) ;
716729 return ; // don't bother finding other problems.
717730 }
718731 }
@@ -737,8 +750,10 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
737750
738751 debug ! ( "check_if_path_is_moved part2 lvalue: {:?}" , lvalue) ;
739752 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) ;
742757 return ; // don't bother finding other problems.
743758 }
744759 }
@@ -1083,17 +1098,47 @@ mod prefixes {
10831098}
10841099
10851100impl < ' 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 ,
10871102 _context : Context ,
10881103 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+ }
10971142 }
10981143
10991144 fn report_move_out_while_borrowed ( & mut self ,
@@ -1396,26 +1441,31 @@ impl ContextKind {
13961441impl < ' b , ' gcx , ' tcx > InProgress < ' b , ' gcx , ' tcx > {
13971442 pub ( super ) fn new ( borrows : DataflowResults < Borrows < ' b , ' gcx , ' tcx > > ,
13981443 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 > > )
14001446 -> Self {
14011447 InProgress {
14021448 borrows : FlowInProgress :: new ( borrows) ,
14031449 inits : FlowInProgress :: new ( inits) ,
14041450 uninits : FlowInProgress :: new ( uninits) ,
1451+ move_outs : FlowInProgress :: new ( move_out)
14051452 }
14061453 }
14071454
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
14121460 XB : FnMut ( & mut FlowInProgress < Borrows < ' b , ' gcx , ' tcx > > ) ,
14131461 XI : FnMut ( & mut FlowInProgress < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ) ,
14141462 XU : FnMut ( & mut FlowInProgress < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ) ,
1463+ XM : FnMut ( & mut FlowInProgress < MovingOutStatements < ' b , ' gcx , ' tcx > > ) ,
14151464 {
14161465 xform_borrows ( & mut self . borrows ) ;
14171466 xform_inits ( & mut self . inits ) ;
14181467 xform_uninits ( & mut self . uninits ) ;
1468+ xform_move_outs ( & mut self . move_outs ) ;
14191469 }
14201470
14211471 fn summary ( & self ) -> String {
@@ -1461,6 +1511,17 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
14611511 & self . uninits . base_results . operator ( ) . move_data ( ) . move_paths [ mpi_uninit] ;
14621512 s. push_str ( & format ! ( "{}" , move_path) ) ;
14631513 } ) ;
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+ } ) ;
14641525 s. push_str ( "]" ) ;
14651526
14661527 return s;
0 commit comments