@@ -35,6 +35,17 @@ use dataflow::move_paths::indexes::MoveOutIndex;
35
35
use dataflow:: move_paths:: MovePathIndex ;
36
36
use util:: borrowck_errors:: { BorrowckErrors , Origin } ;
37
37
38
+ #[ derive( Debug ) ]
39
+ struct MoveSite {
40
+ /// Index of the "move out" that we found. The `MoveData` can
41
+ /// then tell us where the move occurred.
42
+ moi : MoveOutIndex ,
43
+
44
+ /// True if we traversed a back edge while walking from the point
45
+ /// of error to the move site.
46
+ traversed_back_edge : bool
47
+ }
48
+
38
49
impl < ' cx , ' gcx , ' tcx > MirBorrowckCtxt < ' cx , ' gcx , ' tcx > {
39
50
pub ( super ) fn report_use_of_moved_or_uninitialized (
40
51
& mut self ,
@@ -53,10 +64,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
53
64
. or_else ( || self . borrow_spans ( span, context. loc ) ) ;
54
65
let span = use_spans. args_or_use ( ) ;
55
66
56
- let mois = self . get_moved_indexes ( context, mpi) ;
57
- debug ! ( "report_use_of_moved_or_uninitialized: mois={:?}" , mois) ;
67
+ let move_site_vec = self . get_moved_indexes ( context, mpi) ;
68
+ debug ! (
69
+ "report_use_of_moved_or_uninitialized: move_site_vec={:?}" ,
70
+ move_site_vec
71
+ ) ;
72
+ let move_out_indices: Vec < _ > = move_site_vec
73
+ . iter ( )
74
+ . map ( |move_site| move_site. moi )
75
+ . collect ( ) ;
58
76
59
- if mois . is_empty ( ) {
77
+ if move_out_indices . is_empty ( ) {
60
78
let root_place = self . prefixes ( & place, PrefixSet :: All ) . last ( ) . unwrap ( ) ;
61
79
62
80
if self . uninitialized_error_reported
@@ -91,14 +109,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
91
109
92
110
err. buffer ( & mut self . errors_buffer ) ;
93
111
} else {
94
- if let Some ( ( reported_place, _) ) = self . move_error_reported . get ( & mois ) {
112
+ if let Some ( ( reported_place, _) ) = self . move_error_reported . get ( & move_out_indices ) {
95
113
if self . prefixes ( & reported_place, PrefixSet :: All )
96
114
. any ( |p| p == place)
97
115
{
98
116
debug ! (
99
117
"report_use_of_moved_or_uninitialized place: error suppressed \
100
118
mois={:?}",
101
- mois
119
+ move_out_indices
102
120
) ;
103
121
return ;
104
122
}
@@ -115,8 +133,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
115
133
) ;
116
134
117
135
let mut is_loop_move = false ;
118
- for moi in & mois {
119
- let move_out = self . move_data . moves [ * moi] ;
136
+ for move_site in & move_site_vec {
137
+ let move_out = self . move_data . moves [ ( * move_site ) . moi ] ;
120
138
let moved_place = & self . move_data . move_paths [ move_out. path ] . place ;
121
139
122
140
let move_spans = self . move_spans ( moved_place, move_out. source ) ;
@@ -131,9 +149,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
131
149
if span == move_span {
132
150
err. span_label (
133
151
span,
134
- format ! ( "value moved{} here in previous iteration of loop" , move_msg) ,
152
+ format ! ( "value moved{} here, in previous iteration of loop" , move_msg) ,
135
153
) ;
136
154
is_loop_move = true ;
155
+ } else if move_site. traversed_back_edge {
156
+ err. span_label (
157
+ move_span,
158
+ format ! (
159
+ "value moved{} here, in previous iteration of loop" ,
160
+ move_msg
161
+ ) ,
162
+ ) ;
137
163
} else {
138
164
err. span_label ( move_span, format ! ( "value moved{} here" , move_msg) ) ;
139
165
move_spans. var_span_label ( & mut err, "variable moved due to use in closure" ) ;
@@ -171,7 +197,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
171
197
} ;
172
198
173
199
if needs_note {
174
- let mpi = self . move_data . moves [ mois [ 0 ] ] . path ;
200
+ let mpi = self . move_data . moves [ move_out_indices [ 0 ] ] . path ;
175
201
let place = & self . move_data . move_paths [ mpi] . place ;
176
202
177
203
if let Some ( ty) = self . retrieve_type_for_place ( place) {
@@ -192,8 +218,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
192
218
}
193
219
}
194
220
195
- if let Some ( ( _, mut old_err) ) =
196
- self . move_error_reported . insert ( mois , ( place. clone ( ) , err) )
221
+ if let Some ( ( _, mut old_err) ) = self . move_error_reported
222
+ . insert ( move_out_indices , ( place. clone ( ) , err) )
197
223
{
198
224
// Cancel the old error so it doesn't ICE.
199
225
old_err. cancel ( ) ;
@@ -733,29 +759,32 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
733
759
err
734
760
}
735
761
736
- fn get_moved_indexes ( & mut self , context : Context , mpi : MovePathIndex ) -> Vec < MoveOutIndex > {
762
+ fn get_moved_indexes ( & mut self , context : Context , mpi : MovePathIndex ) -> Vec < MoveSite > {
737
763
let mir = self . mir ;
738
764
739
765
let mut stack = Vec :: new ( ) ;
740
- stack. extend ( mir. predecessor_locations ( context. loc ) ) ;
766
+ stack. extend ( mir. predecessor_locations ( context. loc ) . map ( |predecessor| {
767
+ let is_back_edge = context. loc . dominates ( predecessor, & self . dominators ) ;
768
+ ( predecessor, is_back_edge)
769
+ } ) ) ;
741
770
742
771
let mut visited = FxHashSet ( ) ;
743
772
let mut result = vec ! [ ] ;
744
773
745
- ' dfs: while let Some ( l ) = stack. pop ( ) {
774
+ ' dfs: while let Some ( ( location , is_back_edge ) ) = stack. pop ( ) {
746
775
debug ! (
747
- "report_use_of_moved_or_uninitialized: current_location={:?}" ,
748
- l
776
+ "report_use_of_moved_or_uninitialized: ( current_location={:?}, back_edge={}) " ,
777
+ location , is_back_edge
749
778
) ;
750
779
751
- if !visited. insert ( l ) {
780
+ if !visited. insert ( location ) {
752
781
continue ;
753
782
}
754
783
755
784
// check for moves
756
- let stmt_kind = mir[ l . block ]
785
+ let stmt_kind = mir[ location . block ]
757
786
. statements
758
- . get ( l . statement_index )
787
+ . get ( location . statement_index )
759
788
. map ( |s| & s. kind ) ;
760
789
if let Some ( StatementKind :: StorageDead ( ..) ) = stmt_kind {
761
790
// this analysis only tries to find moves explicitly
@@ -774,11 +803,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
774
803
let move_paths = & self . move_data . move_paths ;
775
804
mpis. extend ( move_paths[ mpi] . parents ( move_paths) ) ;
776
805
777
- for moi in & self . move_data . loc_map [ l ] {
806
+ for moi in & self . move_data . loc_map [ location ] {
778
807
debug ! ( "report_use_of_moved_or_uninitialized: moi={:?}" , moi) ;
779
808
if mpis. contains ( & self . move_data . moves [ * moi] . path ) {
780
809
debug ! ( "report_use_of_moved_or_uninitialized: found" ) ;
781
- result. push ( * moi) ;
810
+ result. push ( MoveSite {
811
+ moi : * moi,
812
+ traversed_back_edge : is_back_edge,
813
+ } ) ;
782
814
783
815
// Strictly speaking, we could continue our DFS here. There may be
784
816
// other moves that can reach the point of error. But it is kind of
@@ -807,7 +839,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
807
839
self . infcx . tcx ,
808
840
self . mir ,
809
841
self . move_data ,
810
- l ,
842
+ location ,
811
843
|m| {
812
844
if m == mpi {
813
845
any_match = true ;
@@ -818,7 +850,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
818
850
continue ' dfs;
819
851
}
820
852
821
- stack. extend ( mir. predecessor_locations ( l) ) ;
853
+ stack. extend ( mir. predecessor_locations ( location) . map ( |predecessor| {
854
+ let back_edge = location. dominates ( predecessor, & self . dominators ) ;
855
+ ( predecessor, is_back_edge || back_edge)
856
+ } ) ) ;
822
857
}
823
858
824
859
result
0 commit comments