@@ -22,17 +22,15 @@ use std::mem;
2222use super :: abs_domain:: Lift ;
2323
2424use super :: { LocationMap , MoveData , MovePath , MovePathLookup , MovePathIndex , MoveOut , MoveOutIndex } ;
25+ use super :: { MoveError } ;
26+ use super :: IllegalMoveOriginKind :: * ;
2527
26- pub ( super ) struct MoveDataBuilder < ' a , ' tcx : ' a > {
28+ struct MoveDataBuilder < ' a , ' tcx : ' a > {
2729 mir : & ' a Mir < ' tcx > ,
2830 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
2931 param_env : ty:: ParamEnv < ' tcx > ,
3032 data : MoveData < ' tcx > ,
31- }
32-
33- pub enum MovePathError {
34- IllegalMove ,
35- UnionMove { path : MovePathIndex } ,
33+ errors : Vec < MoveError < ' tcx > > ,
3634}
3735
3836impl < ' a , ' tcx > MoveDataBuilder < ' a , ' tcx > {
@@ -47,6 +45,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
4745 mir,
4846 tcx,
4947 param_env,
48+ errors : Vec :: new ( ) ,
5049 data : MoveData {
5150 moves : IndexVec :: new ( ) ,
5251 loc_map : LocationMap :: new ( mir) ,
@@ -94,13 +93,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
9493 ///
9594 /// Maybe we should have separate "borrowck" and "moveck" modes.
9695 fn move_path_for ( & mut self , lval : & Lvalue < ' tcx > )
97- -> Result < MovePathIndex , MovePathError >
96+ -> Result < MovePathIndex , MoveError < ' tcx > >
9897 {
9998 debug ! ( "lookup({:?})" , lval) ;
10099 match * lval {
101100 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 ) ) ,
104102 Lvalue :: Projection ( ref proj) => {
105103 self . move_path_for_projection ( lval, proj)
106104 }
@@ -116,25 +114,32 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
116114 fn move_path_for_projection ( & mut self ,
117115 lval : & Lvalue < ' tcx > ,
118116 proj : & LvalueProjection < ' tcx > )
119- -> Result < MovePathIndex , MovePathError >
117+ -> Result < MovePathIndex , MoveError < ' tcx > >
120118 {
121119 let base = try!( self . move_path_for ( & proj. base ) ) ;
122120 let lv_ty = proj. base . ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
123121 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 ) ) ,
127124 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+ } ) ) ,
129128 // move out of union - always move the entire union
130129 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+ } ) ) ,
138143 _ => {
139144 // FIXME: still badly broken
140145 }
@@ -156,7 +161,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
156161 }
157162 }
158163
159- fn finalize ( self ) -> MoveData < ' tcx > {
164+ fn finalize ( self ) -> Result < MoveData < ' tcx > , ( MoveData < ' tcx > , Vec < MoveError < ' tcx > > ) > {
160165 debug ! ( "{}" , {
161166 debug!( "moves for {:?}:" , self . mir. span) ;
162167 for ( j, mo) in self . data. moves. iter_enumerated( ) {
@@ -168,14 +173,20 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
168173 }
169174 "done dumping moves"
170175 } ) ;
171- self . data
176+
177+ if self . errors . len ( ) > 0 {
178+ Err ( ( self . data , self . errors ) )
179+ } else {
180+ Ok ( self . data )
181+ }
172182 }
173183}
174184
175185pub ( super ) fn gather_moves < ' a , ' tcx > ( mir : & Mir < ' tcx > ,
176186 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
177187 param_env : ty:: ParamEnv < ' tcx > )
178- -> MoveData < ' tcx > {
188+ -> Result < MoveData < ' tcx > ,
189+ ( MoveData < ' tcx > , Vec < MoveError < ' tcx > > ) > {
179190 let mut builder = MoveDataBuilder :: new ( mir, tcx, param_env) ;
180191
181192 for ( bb, block) in mir. basic_blocks ( ) . iter_enumerated ( ) {
@@ -317,13 +328,10 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
317328 }
318329
319330 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 ;
327335 }
328336 } ;
329337 let move_out = self . data . moves . push ( MoveOut { path : path, source : loc } ) ;
0 commit comments