@@ -248,16 +248,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
248248 local : Local ,
249249 ) -> InterpResult < ' tcx , & ' a interpret:: Operand < Self :: Provenance > > {
250250 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-
251+ // Applying restrictions here is meaningless since they can be circumvented via `force_allocation`.
261252 l. access ( )
262253 }
263254
@@ -431,7 +422,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
431422
432423 fn get_const ( & self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
433424 let op = match self . ecx . eval_place_to_op ( place, None ) {
434- Ok ( op) => op,
425+ Ok ( op) => {
426+ if matches ! ( * op, interpret:: Operand :: Immediate ( Immediate :: Uninit ) ) {
427+ // Make sure nobody accidentally uses this value.
428+ return None ;
429+ }
430+ op
431+ }
435432 Err ( e) => {
436433 trace ! ( "get_const failed: {}" , e) ;
437434 return None ;
@@ -643,6 +640,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
643640 if rvalue. needs_subst ( ) {
644641 return None ;
645642 }
643+ if !rvalue
644+ . ty ( & self . ecx . frame ( ) . body . local_decls , * self . ecx . tcx )
645+ . is_sized ( self . ecx . tcx , self . param_env )
646+ {
647+ // the interpreter doesn't support unsized locals (only unsized arguments),
648+ // but rustc does (in a kinda broken way), so we have to skip them here
649+ return None ;
650+ }
646651
647652 if self . tcx . sess . mir_opt_level ( ) >= 4 {
648653 self . eval_rvalue_with_identities ( rvalue, place)
@@ -660,18 +665,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
660665 self . use_ecx ( |this| match rvalue {
661666 Rvalue :: BinaryOp ( op, box ( left, right) )
662667 | Rvalue :: CheckedBinaryOp ( op, box ( left, right) ) => {
663- let l = this. ecx . eval_operand ( left, None ) ;
664- let r = this. ecx . eval_operand ( right, None ) ;
668+ let l = this. ecx . eval_operand ( left, None ) . and_then ( |x| this. ecx . read_immediate ( & x) ) ;
669+ let r =
670+ this. ecx . eval_operand ( right, None ) . and_then ( |x| this. ecx . read_immediate ( & x) ) ;
665671
666672 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) ,
673+ ( Ok ( x) , Err ( _) ) | ( Err ( _) , Ok ( x) ) => x , // exactly one side is known
674+ ( Err ( e) , Err ( _) ) => return Err ( e) , // neither side is known
675+ ( Ok ( _) , Ok ( _) ) => return this. ecx . eval_rvalue_into_place ( rvalue, place) , // both sides are known
670676 } ;
671677
672678 if !matches ! ( const_arg. layout. abi, abi:: Abi :: Scalar ( ..) ) {
673679 // We cannot handle Scalar Pair stuff.
674- return this. ecx . eval_rvalue_into_place ( rvalue, place) ;
680+ // No point in calling `eval_rvalue_into_place`, since only one side is known
681+ throw_machine_stop_str ! ( "cannot optimize this" )
675682 }
676683
677684 let arg_value = const_arg. to_scalar ( ) . to_bits ( const_arg. layout . size ) ?;
@@ -696,7 +703,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
696703 this. ecx . write_immediate ( * const_arg, & dest)
697704 }
698705 }
699- _ => this . ecx . eval_rvalue_into_place ( rvalue , place ) ,
706+ _ => throw_machine_stop_str ! ( "cannot optimize this" ) ,
700707 }
701708 }
702709 _ => this. ecx . eval_rvalue_into_place ( rvalue, place) ,
@@ -1073,7 +1080,11 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
10731080 if let Some ( ref value) = self . eval_operand ( & cond) {
10741081 trace ! ( "assertion on {:?} should be {:?}" , value, expected) ;
10751082 let expected = Scalar :: from_bool ( * expected) ;
1076- let value_const = self . ecx . read_scalar ( & value) . unwrap ( ) ;
1083+ let Ok ( value_const) = self . ecx . read_scalar ( & value) else {
1084+ // FIXME should be used use_ecx rather than a local match... but we have
1085+ // quite a few of these read_scalar/read_immediate that need fixing.
1086+ return
1087+ } ;
10771088 if expected != value_const {
10781089 // Poison all places this operand references so that further code
10791090 // doesn't use the invalid value
0 commit comments