@@ -243,24 +243,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
243243 throw_machine_stop_str ! ( "pointer arithmetic or comparisons aren't supported in ConstProp" )
244244 }
245245
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-
264246 fn access_local_mut < ' a > (
265247 ecx : & ' a mut InterpCx < ' mir , ' tcx , Self > ,
266248 frame : usize ,
@@ -431,7 +413,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
431413
432414 fn get_const ( & self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
433415 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+ }
435423 Err ( e) => {
436424 trace ! ( "get_const failed: {}" , e) ;
437425 return None ;
@@ -643,6 +631,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
643631 if rvalue. needs_subst ( ) {
644632 return None ;
645633 }
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+ }
646642
647643 if self . tcx . sess . mir_opt_level ( ) >= 4 {
648644 self . eval_rvalue_with_identities ( rvalue, place)
@@ -660,18 +656,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
660656 self . use_ecx ( |this| match rvalue {
661657 Rvalue :: BinaryOp ( op, box ( left, right) )
662658 | 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) ) ;
665662
666663 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
670667 } ;
671668
672669 if !matches ! ( const_arg. layout. abi, abi:: Abi :: Scalar ( ..) ) {
673670 // 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" )
675673 }
676674
677675 let arg_value = const_arg. to_scalar ( ) . to_bits ( const_arg. layout . size ) ?;
@@ -696,7 +694,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
696694 this. ecx . write_immediate ( * const_arg, & dest)
697695 }
698696 }
699- _ => this . ecx . eval_rvalue_into_place ( rvalue , place ) ,
697+ _ => throw_machine_stop_str ! ( "cannot optimize this" ) ,
700698 }
701699 }
702700 _ => this. ecx . eval_rvalue_into_place ( rvalue, place) ,
@@ -1073,7 +1071,11 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
10731071 if let Some ( ref value) = self . eval_operand ( & cond) {
10741072 trace ! ( "assertion on {:?} should be {:?}" , value, expected) ;
10751073 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+ } ;
10771079 if expected != value_const {
10781080 // Poison all places this operand references so that further code
10791081 // doesn't use the invalid value
0 commit comments