@@ -22,17 +22,15 @@ use std::mem;
22
22
use super :: abs_domain:: Lift ;
23
23
24
24
use super :: { LocationMap , MoveData , MovePath , MovePathLookup , MovePathIndex , MoveOut , MoveOutIndex } ;
25
+ use super :: { MoveError } ;
26
+ use super :: IllegalMoveOriginKind :: * ;
25
27
26
- pub ( super ) struct MoveDataBuilder < ' a , ' tcx : ' a > {
28
+ struct MoveDataBuilder < ' a , ' tcx : ' a > {
27
29
mir : & ' a Mir < ' tcx > ,
28
30
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
29
31
param_env : ty:: ParamEnv < ' tcx > ,
30
32
data : MoveData < ' tcx > ,
31
- }
32
-
33
- pub enum MovePathError {
34
- IllegalMove ,
35
- UnionMove { path : MovePathIndex } ,
33
+ errors : Vec < MoveError < ' tcx > > ,
36
34
}
37
35
38
36
impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
@@ -47,6 +45,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
47
45
mir,
48
46
tcx,
49
47
param_env,
48
+ errors : Vec :: new ( ) ,
50
49
data : MoveData {
51
50
moves : IndexVec :: new ( ) ,
52
51
loc_map : LocationMap :: new ( mir) ,
@@ -94,13 +93,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
94
93
///
95
94
/// Maybe we should have separate "borrowck" and "moveck" modes.
96
95
fn move_path_for ( & mut self , lval : & Lvalue < ' tcx > )
97
- -> Result < MovePathIndex , MovePathError >
96
+ -> Result < MovePathIndex , MoveError < ' tcx > >
98
97
{
99
98
debug ! ( "lookup({:?})" , lval) ;
100
99
match * lval {
101
100
Lvalue :: Local ( local) => Ok ( self . data . rev_lookup . locals [ local] ) ,
102
- // error: can't move out of a static
103
- Lvalue :: Static ( ..) => Err ( MovePathError :: IllegalMove ) ,
101
+ Lvalue :: Static ( ..) => Err ( MoveError :: cannot_move_out_of ( Static ) ) ,
104
102
Lvalue :: Projection ( ref proj) => {
105
103
self . move_path_for_projection ( lval, proj)
106
104
}
@@ -116,25 +114,32 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
116
114
fn move_path_for_projection ( & mut self ,
117
115
lval : & Lvalue < ' tcx > ,
118
116
proj : & LvalueProjection < ' tcx > )
119
- -> Result < MovePathIndex , MovePathError >
117
+ -> Result < MovePathIndex , MoveError < ' tcx > >
120
118
{
121
119
let base = try!( self . move_path_for ( & proj. base ) ) ;
122
120
let lv_ty = proj. base . ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
123
121
match lv_ty. sty {
124
- // error: can't move out of borrowed content
125
- ty:: TyRef ( ..) | ty:: TyRawPtr ( ..) => return Err ( MovePathError :: IllegalMove ) ,
126
- // error: can't move out of struct with destructor
122
+ ty:: TyRef ( ..) | ty:: TyRawPtr ( ..) =>
123
+ return Err ( MoveError :: cannot_move_out_of ( BorrowedContent ) ) ,
127
124
ty:: TyAdt ( adt, _) if adt. has_dtor ( self . tcx ) && !adt. is_box ( ) =>
128
- return Err ( MovePathError :: IllegalMove ) ,
125
+ return Err ( MoveError :: cannot_move_out_of ( InteriorOfTypeWithDestructor {
126
+ container_ty : lv_ty
127
+ } ) ) ,
129
128
// move out of union - always move the entire union
130
129
ty:: TyAdt ( adt, _) if adt. is_union ( ) =>
131
- return Err ( MovePathError :: UnionMove { path : base } ) ,
132
- // error: can't move out of a slice
133
- ty:: TySlice ( ..) =>
134
- return Err ( MovePathError :: IllegalMove ) ,
135
- ty:: TyArray ( ..) => match proj. elem {
136
- // error: can't move out of an array
137
- ProjectionElem :: Index ( ..) => return Err ( MovePathError :: IllegalMove ) ,
130
+ return Err ( MoveError :: UnionMove { path : base } ) ,
131
+ ty:: TySlice ( elem_ty) =>
132
+ return Err ( MoveError :: cannot_move_out_of ( InteriorOfSlice {
133
+ elem_ty, is_index : match proj. elem {
134
+ ProjectionElem :: Index ( ..) => true ,
135
+ _ => false
136
+ } ,
137
+ } ) ) ,
138
+ ty:: TyArray ( elem_ty, _num_elems) => match proj. elem {
139
+ ProjectionElem :: Index ( ..) =>
140
+ return Err ( MoveError :: cannot_move_out_of ( InteriorOfArray {
141
+ elem_ty, is_index : true
142
+ } ) ) ,
138
143
_ => {
139
144
// FIXME: still badly broken
140
145
}
@@ -156,7 +161,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
156
161
}
157
162
}
158
163
159
- fn finalize ( self ) -> MoveData < ' tcx > {
164
+ fn finalize ( self ) -> Result < MoveData < ' tcx > , ( MoveData < ' tcx > , Vec < MoveError < ' tcx > > ) > {
160
165
debug ! ( "{}" , {
161
166
debug!( "moves for {:?}:" , self . mir. span) ;
162
167
for ( j, mo) in self . data. moves. iter_enumerated( ) {
@@ -168,14 +173,20 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
168
173
}
169
174
"done dumping moves"
170
175
} ) ;
171
- self . data
176
+
177
+ if self . errors . len ( ) > 0 {
178
+ Err ( ( self . data , self . errors ) )
179
+ } else {
180
+ Ok ( self . data )
181
+ }
172
182
}
173
183
}
174
184
175
185
pub ( super ) fn gather_moves < ' a , ' tcx > ( mir : & Mir < ' tcx > ,
176
186
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
177
187
param_env : ty:: ParamEnv < ' tcx > )
178
- -> MoveData < ' tcx > {
188
+ -> Result < MoveData < ' tcx > ,
189
+ ( MoveData < ' tcx > , Vec < MoveError < ' tcx > > ) > {
179
190
let mut builder = MoveDataBuilder :: new ( mir, tcx, param_env) ;
180
191
181
192
for ( bb, block) in mir. basic_blocks ( ) . iter_enumerated ( ) {
@@ -317,13 +328,10 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
317
328
}
318
329
319
330
let path = match self . move_path_for ( lval) {
320
- Ok ( path) | Err ( MovePathError :: UnionMove { path } ) => path,
321
- Err ( MovePathError :: IllegalMove ) => {
322
- // Moving out of a bad path. Eventually, this should be a MIR
323
- // borrowck error instead of a bug.
324
- span_bug ! ( self . mir. span,
325
- "Broken MIR: moving out of lvalue {:?}: {:?} at {:?}" ,
326
- lval, lv_ty, loc) ;
331
+ Ok ( path) | Err ( MoveError :: UnionMove { path } ) => path,
332
+ Err ( error @ MoveError :: IllegalMove { .. } ) => {
333
+ self . errors . push ( error) ;
334
+ return ;
327
335
}
328
336
} ;
329
337
let move_out = self . data . moves . push ( MoveOut { path : path, source : loc } ) ;
0 commit comments