@@ -95,82 +95,87 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
9595 -> Result < MovePathIndex , MoveError < ' tcx > >
9696 {
9797 debug ! ( "lookup({:?})" , place) ;
98- match * place {
99- Place :: Base ( PlaceBase :: Local ( local) ) => Ok ( self . builder . data . rev_lookup . locals [ local] ) ,
100- Place :: Base ( PlaceBase :: Static ( ..) ) => {
101- Err ( MoveError :: cannot_move_out_of ( self . loc , Static ) )
102- }
103- Place :: Projection ( ref proj) => {
104- self . move_path_for_projection ( place, proj)
98+ place. iterate ( |place_base, place_projection| {
99+ let mut base = match place_base {
100+ PlaceBase :: Local ( local) => self . builder . data . rev_lookup . locals [ * local] ,
101+ PlaceBase :: Static ( ..) => {
102+ return Err ( MoveError :: cannot_move_out_of ( self . loc , Static ) ) ;
103+ }
104+ } ;
105+
106+ for proj in place_projection {
107+ let mir = self . builder . mir ;
108+ let tcx = self . builder . tcx ;
109+ let place_ty = proj. base . ty ( mir, tcx) . ty ;
110+ match place_ty. sty {
111+ ty:: Ref ( ..) | ty:: RawPtr ( ..) =>
112+ return Err ( MoveError :: cannot_move_out_of (
113+ self . loc ,
114+ BorrowedContent {
115+ target_place : Place :: Projection ( Box :: new ( proj. clone ( ) ) ) ,
116+ } ) ) ,
117+ ty:: Adt ( adt, _) if adt. has_dtor ( tcx) && !adt. is_box ( ) =>
118+ return Err ( MoveError :: cannot_move_out_of ( self . loc ,
119+ InteriorOfTypeWithDestructor {
120+ container_ty : place_ty
121+ } ) ) ,
122+ // move out of union - always move the entire union
123+ ty:: Adt ( adt, _) if adt. is_union ( ) =>
124+ return Err ( MoveError :: UnionMove { path : base } ) ,
125+ ty:: Slice ( _) =>
126+ return Err ( MoveError :: cannot_move_out_of (
127+ self . loc ,
128+ InteriorOfSliceOrArray {
129+ ty : place_ty, is_index : match proj. elem {
130+ ProjectionElem :: Index ( ..) => true ,
131+ _ => false
132+ } ,
133+ } ) ) ,
134+ ty:: Array ( ..) => match proj. elem {
135+ ProjectionElem :: Index ( ..) =>
136+ return Err ( MoveError :: cannot_move_out_of (
137+ self . loc ,
138+ InteriorOfSliceOrArray {
139+ ty : place_ty, is_index : true
140+ } ) ) ,
141+ _ => {
142+ // FIXME: still badly broken
143+ }
144+ } ,
145+ _ => { }
146+ } ;
147+
148+ base = match self
149+ . builder
150+ . data
151+ . rev_lookup
152+ . projections
153+ . entry ( ( base, proj. elem . lift ( ) ) )
154+ {
155+ Entry :: Occupied ( ent) => * ent. get ( ) ,
156+ Entry :: Vacant ( ent) => {
157+ let path = MoveDataBuilder :: new_move_path (
158+ & mut self . builder . data . move_paths ,
159+ & mut self . builder . data . path_map ,
160+ & mut self . builder . data . init_path_map ,
161+ Some ( base) ,
162+ Place :: Projection ( Box :: new ( proj. clone ( ) ) ) ,
163+ ) ;
164+ ent. insert ( path) ;
165+ path
166+ }
167+ } ;
105168 }
106- }
169+
170+ Ok ( base)
171+ } )
107172 }
108173
109174 fn create_move_path ( & mut self , place : & Place < ' tcx > ) {
110175 // This is an non-moving access (such as an overwrite or
111176 // drop), so this not being a valid move path is OK.
112177 let _ = self . move_path_for ( place) ;
113178 }
114-
115- fn move_path_for_projection ( & mut self ,
116- place : & Place < ' tcx > ,
117- proj : & Projection < ' tcx > )
118- -> Result < MovePathIndex , MoveError < ' tcx > >
119- {
120- let base = self . move_path_for ( & proj. base ) ?;
121- let mir = self . builder . mir ;
122- let tcx = self . builder . tcx ;
123- let place_ty = proj. base . ty ( mir, tcx) . ty ;
124- match place_ty. sty {
125- ty:: Ref ( ..) | ty:: RawPtr ( ..) =>
126- return Err ( MoveError :: cannot_move_out_of (
127- self . loc ,
128- BorrowedContent { target_place : place. clone ( ) } ) ) ,
129- ty:: Adt ( adt, _) if adt. has_dtor ( tcx) && !adt. is_box ( ) =>
130- return Err ( MoveError :: cannot_move_out_of ( self . loc ,
131- InteriorOfTypeWithDestructor {
132- container_ty : place_ty
133- } ) ) ,
134- // move out of union - always move the entire union
135- ty:: Adt ( adt, _) if adt. is_union ( ) =>
136- return Err ( MoveError :: UnionMove { path : base } ) ,
137- ty:: Slice ( _) =>
138- return Err ( MoveError :: cannot_move_out_of (
139- self . loc ,
140- InteriorOfSliceOrArray {
141- ty : place_ty, is_index : match proj. elem {
142- ProjectionElem :: Index ( ..) => true ,
143- _ => false
144- } ,
145- } ) ) ,
146- ty:: Array ( ..) => match proj. elem {
147- ProjectionElem :: Index ( ..) =>
148- return Err ( MoveError :: cannot_move_out_of (
149- self . loc ,
150- InteriorOfSliceOrArray {
151- ty : place_ty, is_index : true
152- } ) ) ,
153- _ => {
154- // FIXME: still badly broken
155- }
156- } ,
157- _ => { }
158- } ;
159- match self . builder . data . rev_lookup . projections . entry ( ( base, proj. elem . lift ( ) ) ) {
160- Entry :: Occupied ( ent) => Ok ( * ent. get ( ) ) ,
161- Entry :: Vacant ( ent) => {
162- let path = MoveDataBuilder :: new_move_path (
163- & mut self . builder . data . move_paths ,
164- & mut self . builder . data . path_map ,
165- & mut self . builder . data . init_path_map ,
166- Some ( base) ,
167- place. clone ( )
168- ) ;
169- ent. insert ( path) ;
170- Ok ( path)
171- }
172- }
173- }
174179}
175180
176181impl < ' a , ' gcx , ' tcx > MoveDataBuilder < ' a , ' gcx , ' tcx > {
0 commit comments