@@ -131,6 +131,22 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
131131 Live ( Operand < Tag , Id > ) ,
132132}
133133
134+ impl < Tag : Copy > LocalValue < Tag > {
135+ /// The initial value of a local: ZST get "initialized" because they can be read from without
136+ /// ever having been written to.
137+ fn uninit_local (
138+ layout : TyLayout < ' _ >
139+ ) -> LocalValue < Tag > {
140+ // FIXME: Can we avoid this ZST special case? That would likely require MIR
141+ // generation changes.
142+ if layout. is_zst ( ) {
143+ LocalValue :: Live ( Operand :: Immediate ( Immediate :: Scalar ( Scalar :: zst ( ) . into ( ) ) ) )
144+ } else {
145+ LocalValue :: Uninitialized
146+ }
147+ }
148+ }
149+
134150impl < ' tcx , Tag : Copy > LocalState < ' tcx , Tag > {
135151 pub fn access ( & self ) -> EvalResult < ' tcx , & Operand < Tag > > {
136152 match self . state {
@@ -518,19 +534,15 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
518534 }
519535 } ,
520536 }
521- // FIXME: We initialize live ZST here. This should not be needed if MIR was
522- // consistently generated for ZST, but that seems to not be the case -- there
523- // is MIR (around promoteds in particular) that reads local ZSTs that never
524- // were written to.
537+ // The remaining locals are uninitialized, fill them with `uninit_local`.
538+ // (For ZST this is not a NOP.)
525539 for ( idx, local) in locals. iter_enumerated_mut ( ) {
526540 match local. state {
527541 LocalValue :: Uninitialized => {
528542 // This needs to be properly initialized.
529543 let ty = self . monomorphize ( mir. local_decls [ idx] . ty ) ?;
530544 let layout = self . layout_of ( ty) ?;
531- if layout. is_zst ( ) {
532- local. state = LocalValue :: Live ( self . uninit_operand ( layout) ?) ;
533- }
545+ local. state = LocalValue :: uninit_local ( layout) ;
534546 local. layout = Cell :: new ( Some ( layout) ) ;
535547 }
536548 LocalValue :: Dead => {
@@ -622,9 +634,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
622634 trace ! ( "{:?} is now live" , local) ;
623635
624636 let layout = self . layout_of_local ( self . frame ( ) , local, None ) ?;
625- let init = LocalValue :: Live ( self . uninit_operand ( layout) ? ) ;
637+ let local_val = LocalValue :: uninit_local ( layout) ;
626638 // StorageLive *always* kills the value that's currently stored
627- Ok ( mem:: replace ( & mut self . frame_mut ( ) . locals [ local] . state , init ) )
639+ Ok ( mem:: replace ( & mut self . frame_mut ( ) . locals [ local] . state , local_val ) )
628640 }
629641
630642 /// Returns the old value of the local.
0 commit comments