@@ -59,7 +59,7 @@ impl MirPass for ConstProp {
5959
6060 trace ! ( "ConstProp starting for {:?}" , source. def_id( ) ) ;
6161
62- // steal some data we need from `body`
62+ // Steal some data we need from `body`.
6363 let source_scope_local_data = std:: mem:: replace (
6464 & mut body. source_scope_local_data ,
6565 ClearCrossCrate :: Clear
@@ -188,31 +188,49 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
188188 }
189189 }
190190
191- fn release_stolen_data ( self ) ->
192- ( ClearCrossCrate < IndexVec < SourceScope , SourceScopeLocalData > > ,
193- IndexVec < Promoted , Body < ' tcx > > )
194- {
191+ fn release_stolen_data (
192+ self ,
193+ ) -> (
194+ ClearCrossCrate < IndexVec < SourceScope , SourceScopeLocalData > > ,
195+ IndexVec < Promoted , Body < ' tcx > > ,
196+ ) {
195197 ( self . source_scope_local_data , self . promoted )
196198 }
197199
198200 fn get_const ( & self , local : Local ) -> Option < Const < ' tcx > > {
199201 let l = & self . ecx . frame ( ) . locals [ local] ;
200- if l. value == LocalValue :: Uninitialized || l. value == LocalValue :: Dead {
202+
203+ // If the local is `Unitialized` or `Dead` then we haven't propagated a value into it.
204+ //
205+ // `InterpretCx::access_local()` mostly takes care of this for us however, for ZSTs,
206+ // it will synthesize a value for us. In doing so, that will cause the
207+ // `get_const(l).is_empty()` assert right before we call `set_const()` in `visit_statement`
208+ // to fail.
209+ if let LocalValue :: Uninitialized | LocalValue :: Dead = l. value {
201210 return None ;
202211 }
203212
204213 self . ecx . access_local ( self . ecx . frame ( ) , local, None ) . ok ( )
205214 }
206215
207- fn set_const ( & mut self , local : Local , c : Option < Const < ' tcx > > ) {
208- self . ecx . frame_mut ( ) . locals [ local] =
209- match c {
210- Some ( op_ty) => LocalState {
211- value : LocalValue :: Live ( * op_ty) ,
212- layout : Cell :: new ( Some ( op_ty. layout ) ) ,
213- } ,
214- None => LocalState { value : LocalValue :: Uninitialized , layout : Cell :: new ( None ) } ,
215- } ;
216+ fn set_const ( & mut self , local : Local , c : Const < ' tcx > ) {
217+ let frame = self . ecx . frame_mut ( ) ;
218+
219+ if let Some ( layout) = frame. locals [ local] . layout . get ( ) {
220+ debug_assert_eq ! ( c. layout, layout) ;
221+ }
222+
223+ frame. locals [ local] = LocalState {
224+ value : LocalValue :: Live ( * c) ,
225+ layout : Cell :: new ( Some ( c. layout ) ) ,
226+ } ;
227+ }
228+
229+ fn remove_const ( & mut self , local : Local ) {
230+ self . ecx . frame_mut ( ) . locals [ local] = LocalState {
231+ value : LocalValue :: Uninitialized ,
232+ layout : Cell :: new ( None ) ,
233+ } ;
216234 }
217235
218236 fn use_ecx < F , T > (
@@ -768,7 +786,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
768786 if self . can_const_prop [ local] {
769787 trace ! ( "storing {:?} to {:?}" , value, local) ;
770788 assert ! ( self . get_const( local) . is_none( ) ) ;
771- self . set_const ( local, Some ( value) ) ;
789+ self . set_const ( local, value) ;
772790
773791 if self . should_const_prop ( ) {
774792 self . replace_with_const (
@@ -808,7 +826,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
808826 place = & proj. base ;
809827 }
810828 if let Place :: Base ( PlaceBase :: Local ( local) ) = * place {
811- self . set_const ( local, None ) ;
829+ self . remove_const ( local) ;
812830 }
813831 } ,
814832 Operand :: Constant ( _) => { }
0 commit comments