@@ -296,47 +296,50 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
296
296
297
297
fn eval_place ( & mut self , place : & Place < ' tcx > , source_info : SourceInfo ) -> Option < Const < ' tcx > > {
298
298
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
305
316
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 )
307
319
} ) ?;
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 ( )
322
322
}
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
+ } )
340
343
}
341
344
342
345
fn eval_operand ( & mut self , op : & Operand < ' tcx > , source_info : SourceInfo ) -> Option < Const < ' tcx > > {
0 commit comments