@@ -393,8 +393,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
393
393
. filter ( |ret_layout| {
394
394
!ret_layout. is_zst ( ) && ret_layout. size < Size :: from_bytes ( MAX_ALLOC_LIMIT )
395
395
} )
396
- // hopefully all types will allocate, since large types have already been removed
397
- . and_then ( |ret_layout| ecx. allocate ( ret_layout, MemoryKind :: Stack ) . ok ( ) )
396
+ . and_then ( |ret_layout| {
397
+ let alloc = ecx. allocate ( ret_layout, MemoryKind :: Stack ) ;
398
+ Self :: check_interpresult ( tcx, & alloc) ;
399
+ alloc. ok ( )
400
+ } )
398
401
. map ( Into :: into) ;
399
402
400
403
ecx. push_stack_frame (
@@ -418,11 +421,27 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
418
421
}
419
422
}
420
423
424
+ /// Some `InterpError`s could be ignored but must not be to ensure that queries are stable.
425
+ fn check_interpresult < T > ( tcx : TyCtxt < ' tcx > , error : & InterpResult < ' tcx , T > ) {
426
+ if let Err ( e) = error {
427
+ if matches ! (
428
+ e. kind( ) ,
429
+ InterpError :: ResourceExhaustion ( ResourceExhaustionInfo :: MemoryExhausted )
430
+ ) {
431
+ // Memory errors can't be ignored since otherwise the amount of available
432
+ // memory influences the result of optimization and the build. The error
433
+ // doesn't need to be fatal since no code will actually be generated anyways.
434
+ tcx. sess . fatal ( "memory exhausted during optimization" ) ;
435
+ }
436
+ }
437
+ }
438
+
421
439
fn get_const ( & self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
422
440
let op = match self . ecx . eval_place_to_op ( place, None ) {
423
441
Ok ( op) => op,
424
442
Err ( e) => {
425
443
trace ! ( "get_const failed: {}" , e) ;
444
+ Self :: check_interpresult :: < ( ) > ( self . tcx , & Err ( e) ) ;
426
445
return None ;
427
446
}
428
447
} ;
@@ -524,7 +543,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
524
543
/// Returns the value, if any, of evaluating `place`.
525
544
fn eval_place ( & mut self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
526
545
trace ! ( "eval_place(place={:?})" , place) ;
527
- self . use_ecx ( |this| this. ecx . eval_place_to_op ( place, None ) )
546
+ let tcx = self . tcx ;
547
+ self . use_ecx ( |this| {
548
+ let val = this. ecx . eval_place_to_op ( place, None ) ;
549
+ Self :: check_interpresult ( tcx, & val) ;
550
+ val
551
+ } )
528
552
}
529
553
530
554
/// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant`
@@ -585,8 +609,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
585
609
right : & Operand < ' tcx > ,
586
610
source_info : SourceInfo ,
587
611
) -> Option < ( ) > {
588
- let r = self . use_ecx ( |this| this. ecx . read_immediate ( & this. ecx . eval_operand ( right, None ) ?) ) ;
589
- let l = self . use_ecx ( |this| this. ecx . read_immediate ( & this. ecx . eval_operand ( left, None ) ?) ) ;
612
+ let tcx = self . tcx ;
613
+ let r = self . use_ecx ( |this| {
614
+ let val = this. ecx . read_immediate ( & this. ecx . eval_operand ( right, None ) ?) ;
615
+ Self :: check_interpresult ( tcx, & val) ;
616
+ val
617
+ } ) ;
618
+ let l = self . use_ecx ( |this| {
619
+ let val = this. ecx . read_immediate ( & this. ecx . eval_operand ( left, None ) ?) ;
620
+ Self :: check_interpresult ( tcx, & val) ;
621
+ val
622
+ } ) ;
590
623
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
591
624
if op == BinOp :: Shr || op == BinOp :: Shl {
592
625
let r = r?;
@@ -752,18 +785,24 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
752
785
rvalue : & Rvalue < ' tcx > ,
753
786
place : Place < ' tcx > ,
754
787
) -> Option < ( ) > {
788
+ let tcx = self . tcx ;
755
789
self . use_ecx ( |this| {
756
790
match rvalue {
757
791
Rvalue :: BinaryOp ( op, box ( left, right) )
758
792
| Rvalue :: CheckedBinaryOp ( op, box ( left, right) ) => {
759
793
let l = this. ecx . eval_operand ( left, None ) ;
760
794
let r = this. ecx . eval_operand ( right, None ) ;
795
+ Self :: check_interpresult ( tcx, & l) ;
796
+ Self :: check_interpresult ( tcx, & r) ;
761
797
762
798
let const_arg = match ( l, r) {
763
799
( Ok ( ref x) , Err ( _) ) | ( Err ( _) , Ok ( ref x) ) => this. ecx . read_immediate ( x) ?,
764
800
( Err ( e) , Err ( _) ) => return Err ( e) ,
765
801
( Ok ( _) , Ok ( _) ) => {
766
- this. ecx . eval_rvalue_into_place ( rvalue, place) ?;
802
+ Self :: check_interpresult (
803
+ tcx,
804
+ & this. ecx . eval_rvalue_into_place ( rvalue, place) ,
805
+ ) ;
767
806
return Ok ( ( ) ) ;
768
807
}
769
808
} ;
@@ -799,12 +838,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
799
838
}
800
839
}
801
840
_ => {
802
- this. ecx . eval_rvalue_into_place ( rvalue, place) ?;
841
+ let res = this. ecx . eval_rvalue_into_place ( rvalue, place) ;
842
+ Self :: check_interpresult ( tcx, & res) ;
843
+ res?
803
844
}
804
845
}
805
846
}
806
847
_ => {
807
- this. ecx . eval_rvalue_into_place ( rvalue, place) ?;
848
+ let res = this. ecx . eval_rvalue_into_place ( rvalue, place) ;
849
+ Self :: check_interpresult ( tcx, & res) ;
850
+ res?
808
851
}
809
852
}
810
853
0 commit comments