@@ -296,47 +296,50 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
296296
297297 fn eval_place ( & mut self , place : & Place < ' tcx > , source_info : SourceInfo ) -> Option < Const < ' tcx > > {
298298 trace ! ( "eval_place(place={:?})" , place) ;
299- match * place {
300- Place :: Base ( PlaceBase :: Local ( loc) ) => self . places [ loc] . clone ( ) ,
301- Place :: Projection ( ref proj) => match proj. elem {
302- ProjectionElem :: Field ( field, _) => {
303- trace ! ( "field proj on {:?}" , proj. base) ;
304- let base = self . eval_place ( & proj. base , source_info) ?;
299+ place. iterate ( |place_base, place_projection| {
300+ let mut eval = match place_base {
301+ PlaceBase :: Local ( loc) => self . places [ * loc] . clone ( ) ?,
302+ PlaceBase :: Static ( box Static { kind : StaticKind :: Promoted ( promoted) , ..} ) => {
303+ let generics = self . tcx . generics_of ( self . source . def_id ( ) ) ;
304+ if generics. requires_monomorphization ( self . tcx ) {
305+ // FIXME: can't handle code with generics
306+ return None ;
307+ }
308+ let substs = InternalSubsts :: identity_for_item ( self . tcx , self . source . def_id ( ) ) ;
309+ let instance = Instance :: new ( self . source . def_id ( ) , substs) ;
310+ let cid = GlobalId {
311+ instance,
312+ promoted : Some ( * promoted) ,
313+ } ;
314+ // cannot use `const_eval` here, because that would require having the MIR
315+ // for the current function available, but we're producing said MIR right now
305316 let res = self . use_ecx ( source_info, |this| {
306- this. ecx . operand_field ( base, field. index ( ) as u64 )
317+ let mir = & this. promoted [ * promoted] ;
318+ eval_promoted ( this. tcx , cid, mir, this. param_env )
307319 } ) ?;
308- Some ( res)
309- } ,
310- // We could get more projections by using e.g., `operand_projection`,
311- // but we do not even have the stack frame set up properly so
312- // an `Index` projection would throw us off-track.
313- _ => None ,
314- } ,
315- Place :: Base (
316- PlaceBase :: Static ( box Static { kind : StaticKind :: Promoted ( promoted) , ..} )
317- ) => {
318- let generics = self . tcx . generics_of ( self . source . def_id ( ) ) ;
319- if generics. requires_monomorphization ( self . tcx ) {
320- // FIXME: can't handle code with generics
321- return None ;
320+ trace ! ( "evaluated promoted {:?} to {:?}" , promoted, res) ;
321+ res. into ( )
322322 }
323- let substs = InternalSubsts :: identity_for_item ( self . tcx , self . source . def_id ( ) ) ;
324- let instance = Instance :: new ( self . source . def_id ( ) , substs) ;
325- let cid = GlobalId {
326- instance,
327- promoted : Some ( promoted) ,
328- } ;
329- // cannot use `const_eval` here, because that would require having the MIR
330- // for the current function available, but we're producing said MIR right now
331- let res = self . use_ecx ( source_info, |this| {
332- let mir = & this. promoted [ promoted] ;
333- eval_promoted ( this. tcx , cid, mir, this. param_env )
334- } ) ?;
335- trace ! ( "evaluated promoted {:?} to {:?}" , promoted, res) ;
336- Some ( res. into ( ) )
337- } ,
338- _ => None ,
339- }
323+ _ => return None ,
324+ } ;
325+
326+ for proj in place_projection {
327+ match proj. elem {
328+ ProjectionElem :: Field ( field, _) => {
329+ trace ! ( "field proj on {:?}" , proj. base) ;
330+ eval = self . use_ecx ( source_info, |this| {
331+ this. ecx . operand_field ( eval, field. index ( ) as u64 )
332+ } ) ?;
333+ } ,
334+ // We could get more projections by using e.g., `operand_projection`,
335+ // but we do not even have the stack frame set up properly so
336+ // an `Index` projection would throw us off-track.
337+ _ => return None ,
338+ }
339+ }
340+
341+ Some ( eval)
342+ } )
340343 }
341344
342345 fn eval_operand ( & mut self , op : & Operand < ' tcx > , source_info : SourceInfo ) -> Option < Const < ' tcx > > {
0 commit comments