@@ -131,6 +131,22 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
131
131
Live ( Operand < Tag , Id > ) ,
132
132
}
133
133
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
+
134
150
impl < ' tcx , Tag : Copy > LocalState < ' tcx , Tag > {
135
151
pub fn access ( & self ) -> EvalResult < ' tcx , & Operand < Tag > > {
136
152
match self . state {
@@ -518,19 +534,15 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
518
534
}
519
535
} ,
520
536
}
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.)
525
539
for ( idx, local) in locals. iter_enumerated_mut ( ) {
526
540
match local. state {
527
541
LocalValue :: Uninitialized => {
528
542
// This needs to be properly initialized.
529
543
let ty = self . monomorphize ( mir. local_decls [ idx] . ty ) ?;
530
544
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) ;
534
546
local. layout = Cell :: new ( Some ( layout) ) ;
535
547
}
536
548
LocalValue :: Dead => {
@@ -622,9 +634,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
622
634
trace ! ( "{:?} is now live" , local) ;
623
635
624
636
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) ;
626
638
// 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 ) )
628
640
}
629
641
630
642
/// Returns the old value of the local.
0 commit comments