@@ -31,7 +31,7 @@ use dataflow::{do_dataflow};
31
31
use dataflow:: { MoveDataParamEnv } ;
32
32
use dataflow:: { BitDenotation , BlockSets , DataflowResults , DataflowResultsConsumer } ;
33
33
use dataflow:: { MaybeInitializedLvals , MaybeUninitializedLvals } ;
34
- use dataflow:: { MovingOutStatements } ;
34
+ use dataflow:: { MovingOutStatements , EverInitializedLvals } ;
35
35
use dataflow:: { Borrows , BorrowData , BorrowIndex } ;
36
36
use dataflow:: move_paths:: { MoveError , IllegalMoveOriginKind } ;
37
37
use dataflow:: move_paths:: { HasMoveData , MoveData , MovePathIndex , LookupResult , MoveOutIndex } ;
@@ -130,6 +130,9 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
130
130
let flow_move_outs = do_dataflow ( tcx, mir, id, & attributes, & dead_unwinds,
131
131
MovingOutStatements :: new ( tcx, mir, & mdpe) ,
132
132
|bd, i| & bd. move_data ( ) . moves [ i] ) ;
133
+ let flow_ever_inits = do_dataflow ( tcx, mir, id, & attributes, & dead_unwinds,
134
+ EverInitializedLvals :: new ( tcx, mir, & mdpe) ,
135
+ |bd, i| & bd. move_data ( ) . inits [ i] ) ;
133
136
134
137
let mut mbcx = MirBorrowckCtxt {
135
138
tcx : tcx,
@@ -143,7 +146,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
143
146
let mut state = InProgress :: new ( flow_borrows,
144
147
flow_inits,
145
148
flow_uninits,
146
- flow_move_outs) ;
149
+ flow_move_outs,
150
+ flow_ever_inits) ;
147
151
148
152
mbcx. analyze_results ( & mut state) ; // entry point for DataflowResultsConsumer
149
153
}
@@ -167,6 +171,7 @@ pub struct InProgress<'b, 'gcx: 'tcx, 'tcx: 'b> {
167
171
inits : FlowInProgress < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ,
168
172
uninits : FlowInProgress < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ,
169
173
move_outs : FlowInProgress < MovingOutStatements < ' b , ' gcx , ' tcx > > ,
174
+ ever_inits : FlowInProgress < EverInitializedLvals < ' b , ' gcx , ' tcx > > ,
170
175
}
171
176
172
177
struct FlowInProgress < BD > where BD : BitDenotation {
@@ -190,7 +195,8 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
190
195
flow_state. each_flow ( |b| b. reset_to_entry_of ( bb) ,
191
196
|i| i. reset_to_entry_of ( bb) ,
192
197
|u| u. reset_to_entry_of ( bb) ,
193
- |m| m. reset_to_entry_of ( bb) ) ;
198
+ |m| m. reset_to_entry_of ( bb) ,
199
+ |e| e. reset_to_entry_of ( bb) ) ;
194
200
}
195
201
196
202
fn reconstruct_statement_effect ( & mut self ,
@@ -199,7 +205,8 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
199
205
flow_state. each_flow ( |b| b. reconstruct_statement_effect ( location) ,
200
206
|i| i. reconstruct_statement_effect ( location) ,
201
207
|u| u. reconstruct_statement_effect ( location) ,
202
- |m| m. reconstruct_statement_effect ( location) ) ;
208
+ |m| m. reconstruct_statement_effect ( location) ,
209
+ |e| e. reconstruct_statement_effect ( location) ) ;
203
210
}
204
211
205
212
fn apply_local_effect ( & mut self ,
@@ -208,7 +215,8 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
208
215
flow_state. each_flow ( |b| b. apply_local_effect ( ) ,
209
216
|i| i. apply_local_effect ( ) ,
210
217
|u| u. apply_local_effect ( ) ,
211
- |m| m. apply_local_effect ( ) ) ;
218
+ |m| m. apply_local_effect ( ) ,
219
+ |e| e. apply_local_effect ( ) ) ;
212
220
}
213
221
214
222
fn reconstruct_terminator_effect ( & mut self ,
@@ -217,7 +225,8 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
217
225
flow_state. each_flow ( |b| b. reconstruct_terminator_effect ( location) ,
218
226
|i| i. reconstruct_terminator_effect ( location) ,
219
227
|u| u. reconstruct_terminator_effect ( location) ,
220
- |m| m. reconstruct_terminator_effect ( location) ) ;
228
+ |m| m. reconstruct_terminator_effect ( location) ,
229
+ |e| e. reconstruct_terminator_effect ( location) ) ;
221
230
}
222
231
223
232
fn visit_block_entry ( & mut self ,
@@ -750,22 +759,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
750
759
}
751
760
752
761
if let Some ( mpi) = self . move_path_for_lvalue ( lvalue) {
753
- if flow_state. inits . curr_state . contains ( & mpi) {
754
- // may already be assigned before reaching this statement;
755
- // report error.
756
- // FIXME: Not ideal, it only finds the assignment that lexically comes first
757
- let assigned_lvalue = & move_data. move_paths [ mpi] . lvalue ;
758
- let assignment_stmt = self . mir . basic_blocks ( ) . iter ( ) . filter_map ( |bb| {
759
- bb. statements . iter ( ) . find ( |stmt| {
760
- if let StatementKind :: Assign ( ref lv, _) = stmt. kind {
761
- * lv == * assigned_lvalue
762
- } else {
763
- false
764
- }
765
- } )
766
- } ) . next ( ) . unwrap ( ) ;
767
- self . report_illegal_reassignment (
768
- context, ( lvalue, span) , assignment_stmt. source_info . span ) ;
762
+ for ii in & move_data. init_path_map [ mpi] {
763
+ if flow_state. ever_inits . curr_state . contains ( ii) {
764
+ let first_assign_span = self . move_data . inits [ * ii] . span ;
765
+ self . report_illegal_reassignment (
766
+ context, ( lvalue, span) , first_assign_span) ;
767
+ break ;
768
+ }
769
769
}
770
770
}
771
771
}
@@ -1586,13 +1586,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1586
1586
_context : Context ,
1587
1587
( lvalue, span) : ( & Lvalue < ' tcx > , Span ) ,
1588
1588
assigned_span : Span ) {
1589
- self . tcx . cannot_reassign_immutable ( span,
1589
+ let mut err = self . tcx . cannot_reassign_immutable ( span,
1590
1590
& self . describe_lvalue ( lvalue) ,
1591
- Origin :: Mir )
1592
- . span_label ( span, "cannot assign twice to immutable variable" )
1593
- . span_label ( assigned_span, format ! ( "first assignment to `{}`" ,
1594
- self . describe_lvalue( lvalue) ) )
1595
- . emit ( ) ;
1591
+ Origin :: Mir ) ;
1592
+ err. span_label ( span, "cannot assign twice to immutable variable" ) ;
1593
+ if span != assigned_span {
1594
+ err. span_label ( assigned_span, format ! ( "first assignment to `{}`" ,
1595
+ self . describe_lvalue( lvalue) ) ) ;
1596
+ }
1597
+ err. emit ( ) ;
1596
1598
}
1597
1599
1598
1600
fn report_assignment_to_static ( & mut self ,
@@ -1852,30 +1854,35 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
1852
1854
pub ( super ) fn new ( borrows : DataflowResults < Borrows < ' b , ' gcx , ' tcx > > ,
1853
1855
inits : DataflowResults < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ,
1854
1856
uninits : DataflowResults < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ,
1855
- move_out : DataflowResults < MovingOutStatements < ' b , ' gcx , ' tcx > > )
1857
+ move_out : DataflowResults < MovingOutStatements < ' b , ' gcx , ' tcx > > ,
1858
+ ever_inits : DataflowResults < EverInitializedLvals < ' b , ' gcx , ' tcx > > )
1856
1859
-> Self {
1857
1860
InProgress {
1858
1861
borrows : FlowInProgress :: new ( borrows) ,
1859
1862
inits : FlowInProgress :: new ( inits) ,
1860
1863
uninits : FlowInProgress :: new ( uninits) ,
1861
- move_outs : FlowInProgress :: new ( move_out)
1864
+ move_outs : FlowInProgress :: new ( move_out) ,
1865
+ ever_inits : FlowInProgress :: new ( ever_inits)
1862
1866
}
1863
1867
}
1864
1868
1865
- fn each_flow < XB , XI , XU , XM > ( & mut self ,
1869
+ fn each_flow < XB , XI , XU , XM , XE > ( & mut self ,
1866
1870
mut xform_borrows : XB ,
1867
1871
mut xform_inits : XI ,
1868
1872
mut xform_uninits : XU ,
1869
- mut xform_move_outs : XM ) where
1873
+ mut xform_move_outs : XM ,
1874
+ mut xform_ever_inits : XE ) where
1870
1875
XB : FnMut ( & mut FlowInProgress < Borrows < ' b , ' gcx , ' tcx > > ) ,
1871
1876
XI : FnMut ( & mut FlowInProgress < MaybeInitializedLvals < ' b , ' gcx , ' tcx > > ) ,
1872
1877
XU : FnMut ( & mut FlowInProgress < MaybeUninitializedLvals < ' b , ' gcx , ' tcx > > ) ,
1873
1878
XM : FnMut ( & mut FlowInProgress < MovingOutStatements < ' b , ' gcx , ' tcx > > ) ,
1879
+ XE : FnMut ( & mut FlowInProgress < EverInitializedLvals < ' b , ' gcx , ' tcx > > ) ,
1874
1880
{
1875
1881
xform_borrows ( & mut self . borrows ) ;
1876
1882
xform_inits ( & mut self . inits ) ;
1877
1883
xform_uninits ( & mut self . uninits ) ;
1878
1884
xform_move_outs ( & mut self . move_outs ) ;
1885
+ xform_ever_inits ( & mut self . ever_inits ) ;
1879
1886
}
1880
1887
1881
1888
fn summary ( & self ) -> String {
@@ -1932,6 +1939,17 @@ impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
1932
1939
& self . move_outs . base_results . operator ( ) . move_data ( ) . moves [ mpi_move_out] ;
1933
1940
s. push_str ( & format ! ( "{:?}" , move_out) ) ;
1934
1941
} ) ;
1942
+ s. push_str ( "] " ) ;
1943
+
1944
+ s. push_str ( "ever_init: [" ) ;
1945
+ let mut saw_one = false ;
1946
+ self . ever_inits . each_state_bit ( |mpi_ever_init| {
1947
+ if saw_one { s. push_str ( ", " ) ; } ;
1948
+ saw_one = true ;
1949
+ let ever_init =
1950
+ & self . ever_inits . base_results . operator ( ) . move_data ( ) . inits [ mpi_ever_init] ;
1951
+ s. push_str ( & format ! ( "{:?}" , ever_init) ) ;
1952
+ } ) ;
1935
1953
s. push_str ( "]" ) ;
1936
1954
1937
1955
return s;
0 commit comments