@@ -243,24 +243,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
243
243
throw_machine_stop_str ! ( "pointer arithmetic or comparisons aren't supported in ConstProp" )
244
244
}
245
245
246
- fn access_local < ' a > (
247
- frame : & ' a Frame < ' mir , ' tcx , Self :: Provenance , Self :: FrameExtra > ,
248
- local : Local ,
249
- ) -> InterpResult < ' tcx , & ' a interpret:: Operand < Self :: Provenance > > {
250
- let l = & frame. locals [ local] ;
251
-
252
- if matches ! (
253
- l. value,
254
- LocalValue :: Live ( interpret:: Operand :: Immediate ( interpret:: Immediate :: Uninit ) )
255
- ) {
256
- // For us "uninit" means "we don't know its value, might be initiailized or not".
257
- // So stop here.
258
- throw_machine_stop_str ! ( "tried to access alocal with unknown value " )
259
- }
260
-
261
- l. access ( )
262
- }
263
-
264
246
fn access_local_mut < ' a > (
265
247
ecx : & ' a mut InterpCx < ' mir , ' tcx , Self > ,
266
248
frame : usize ,
@@ -431,7 +413,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
431
413
432
414
fn get_const ( & self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
433
415
let op = match self . ecx . eval_place_to_op ( place, None ) {
434
- Ok ( op) => op,
416
+ Ok ( op) => {
417
+ if matches ! ( * op, interpret:: Operand :: Immediate ( Immediate :: Uninit ) ) {
418
+ // Make sure nobody accidentally uses this value.
419
+ return None ;
420
+ }
421
+ op
422
+ }
435
423
Err ( e) => {
436
424
trace ! ( "get_const failed: {}" , e) ;
437
425
return None ;
@@ -643,6 +631,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
643
631
if rvalue. needs_subst ( ) {
644
632
return None ;
645
633
}
634
+ if !rvalue
635
+ . ty ( & self . ecx . frame ( ) . body . local_decls , * self . ecx . tcx )
636
+ . is_sized ( self . ecx . tcx , self . param_env )
637
+ {
638
+ // the interpreter doesn't support unsized locals (only unsized arguments),
639
+ // but rustc does (in a kinda broken way), so we have to skip them here
640
+ return None ;
641
+ }
646
642
647
643
if self . tcx . sess . mir_opt_level ( ) >= 4 {
648
644
self . eval_rvalue_with_identities ( rvalue, place)
@@ -660,18 +656,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
660
656
self . use_ecx ( |this| match rvalue {
661
657
Rvalue :: BinaryOp ( op, box ( left, right) )
662
658
| Rvalue :: CheckedBinaryOp ( op, box ( left, right) ) => {
663
- let l = this. ecx . eval_operand ( left, None ) ;
664
- let r = this. ecx . eval_operand ( right, None ) ;
659
+ let l = this. ecx . eval_operand ( left, None ) . and_then ( |x| this. ecx . read_immediate ( & x) ) ;
660
+ let r =
661
+ this. ecx . eval_operand ( right, None ) . and_then ( |x| this. ecx . read_immediate ( & x) ) ;
665
662
666
663
let const_arg = match ( l, r) {
667
- ( Ok ( ref x) , Err ( _) ) | ( Err ( _) , Ok ( ref x) ) => this . ecx . read_immediate ( x ) ? ,
668
- ( Err ( e) , Err ( _) ) => return Err ( e) ,
669
- ( Ok ( _) , Ok ( _) ) => return this. ecx . eval_rvalue_into_place ( rvalue, place) ,
664
+ ( Ok ( x) , Err ( _) ) | ( Err ( _) , Ok ( x) ) => x , // exactly one side is known
665
+ ( Err ( e) , Err ( _) ) => return Err ( e) , // neither side is known
666
+ ( Ok ( _) , Ok ( _) ) => return this. ecx . eval_rvalue_into_place ( rvalue, place) , // both sides are known
670
667
} ;
671
668
672
669
if !matches ! ( const_arg. layout. abi, abi:: Abi :: Scalar ( ..) ) {
673
670
// We cannot handle Scalar Pair stuff.
674
- return this. ecx . eval_rvalue_into_place ( rvalue, place) ;
671
+ // No point in calling `eval_rvalue_into_place`, since only one side is known
672
+ throw_machine_stop_str ! ( "cannot optimize this" )
675
673
}
676
674
677
675
let arg_value = const_arg. to_scalar ( ) . to_bits ( const_arg. layout . size ) ?;
@@ -696,7 +694,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
696
694
this. ecx . write_immediate ( * const_arg, & dest)
697
695
}
698
696
}
699
- _ => this . ecx . eval_rvalue_into_place ( rvalue , place ) ,
697
+ _ => throw_machine_stop_str ! ( "cannot optimize this" ) ,
700
698
}
701
699
}
702
700
_ => this. ecx . eval_rvalue_into_place ( rvalue, place) ,
@@ -1073,7 +1071,11 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
1073
1071
if let Some ( ref value) = self . eval_operand ( & cond) {
1074
1072
trace ! ( "assertion on {:?} should be {:?}" , value, expected) ;
1075
1073
let expected = Scalar :: from_bool ( * expected) ;
1076
- let value_const = self . ecx . read_scalar ( & value) . unwrap ( ) ;
1074
+ let Ok ( value_const) = self . ecx . read_scalar ( & value) else {
1075
+ // FIXME should be used use_ecx rather than a local match... but we have
1076
+ // quite a few of these read_scalar/read_immediate that need fixing.
1077
+ return
1078
+ } ;
1077
1079
if expected != value_const {
1078
1080
// Poison all places this operand references so that further code
1079
1081
// doesn't use the invalid value
0 commit comments