@@ -248,16 +248,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
248
248
local : Local ,
249
249
) -> InterpResult < ' tcx , & ' a interpret:: Operand < Self :: Provenance > > {
250
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
-
251
+ // Applying restrictions here is meaningless since they can be circumvented via `force_allocation`.
261
252
l. access ( )
262
253
}
263
254
@@ -431,7 +422,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
431
422
432
423
fn get_const ( & self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
433
424
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
+ }
435
432
Err ( e) => {
436
433
trace ! ( "get_const failed: {}" , e) ;
437
434
return None ;
@@ -643,6 +640,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
643
640
if rvalue. needs_subst ( ) {
644
641
return None ;
645
642
}
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
+ }
646
651
647
652
if self . tcx . sess . mir_opt_level ( ) >= 4 {
648
653
self . eval_rvalue_with_identities ( rvalue, place)
@@ -660,18 +665,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
660
665
self . use_ecx ( |this| match rvalue {
661
666
Rvalue :: BinaryOp ( op, box ( left, right) )
662
667
| 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) ) ;
665
671
666
672
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
670
676
} ;
671
677
672
678
if !matches ! ( const_arg. layout. abi, abi:: Abi :: Scalar ( ..) ) {
673
679
// 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" )
675
682
}
676
683
677
684
let arg_value = const_arg. to_scalar ( ) . to_bits ( const_arg. layout . size ) ?;
@@ -696,7 +703,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
696
703
this. ecx . write_immediate ( * const_arg, & dest)
697
704
}
698
705
}
699
- _ => this . ecx . eval_rvalue_into_place ( rvalue , place ) ,
706
+ _ => throw_machine_stop_str ! ( "cannot optimize this" ) ,
700
707
}
701
708
}
702
709
_ => this. ecx . eval_rvalue_into_place ( rvalue, place) ,
@@ -1073,7 +1080,11 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
1073
1080
if let Some ( ref value) = self . eval_operand ( & cond) {
1074
1081
trace ! ( "assertion on {:?} should be {:?}" , value, expected) ;
1075
1082
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
+ } ;
1077
1088
if expected != value_const {
1078
1089
// Poison all places this operand references so that further code
1079
1090
// doesn't use the invalid value
0 commit comments