@@ -59,7 +59,7 @@ impl MirPass for ConstProp {
59
59
60
60
trace ! ( "ConstProp starting for {:?}" , source. def_id( ) ) ;
61
61
62
- // steal some data we need from `body`
62
+ // Steal some data we need from `body`.
63
63
let source_scope_local_data = std:: mem:: replace (
64
64
& mut body. source_scope_local_data ,
65
65
ClearCrossCrate :: Clear
@@ -188,31 +188,49 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
188
188
}
189
189
}
190
190
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
+ ) {
195
197
( self . source_scope_local_data , self . promoted )
196
198
}
197
199
198
200
fn get_const ( & self , local : Local ) -> Option < Const < ' tcx > > {
199
201
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 {
201
210
return None ;
202
211
}
203
212
204
213
self . ecx . access_local ( self . ecx . frame ( ) , local, None ) . ok ( )
205
214
}
206
215
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
+ } ;
216
234
}
217
235
218
236
fn use_ecx < F , T > (
@@ -768,7 +786,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
768
786
if self . can_const_prop [ local] {
769
787
trace ! ( "storing {:?} to {:?}" , value, local) ;
770
788
assert ! ( self . get_const( local) . is_none( ) ) ;
771
- self . set_const ( local, Some ( value) ) ;
789
+ self . set_const ( local, value) ;
772
790
773
791
if self . should_const_prop ( ) {
774
792
self . replace_with_const (
@@ -808,7 +826,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
808
826
place = & proj. base ;
809
827
}
810
828
if let Place :: Base ( PlaceBase :: Local ( local) ) = * place {
811
- self . set_const ( local, None ) ;
829
+ self . remove_const ( local) ;
812
830
}
813
831
} ,
814
832
Operand :: Constant ( _) => { }
0 commit comments