@@ -393,8 +393,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
393393 . filter ( |ret_layout| {
394394 !ret_layout. is_zst ( ) && ret_layout. size < Size :: from_bytes ( MAX_ALLOC_LIMIT )
395395 } )
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+ } )
398401 . map ( Into :: into) ;
399402
400403 ecx. push_stack_frame (
@@ -418,11 +421,27 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
418421 }
419422 }
420423
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+
421439 fn get_const ( & self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
422440 let op = match self . ecx . eval_place_to_op ( place, None ) {
423441 Ok ( op) => op,
424442 Err ( e) => {
425443 trace ! ( "get_const failed: {}" , e) ;
444+ Self :: check_interpresult :: < ( ) > ( self . tcx , & Err ( e) ) ;
426445 return None ;
427446 }
428447 } ;
@@ -524,7 +543,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
524543 /// Returns the value, if any, of evaluating `place`.
525544 fn eval_place ( & mut self , place : Place < ' tcx > ) -> Option < OpTy < ' tcx > > {
526545 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+ } )
528552 }
529553
530554 /// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant`
@@ -585,8 +609,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
585609 right : & Operand < ' tcx > ,
586610 source_info : SourceInfo ,
587611 ) -> 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+ } ) ;
590623 // Check for exceeding shifts *even if* we cannot evaluate the LHS.
591624 if op == BinOp :: Shr || op == BinOp :: Shl {
592625 let r = r?;
@@ -752,18 +785,24 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
752785 rvalue : & Rvalue < ' tcx > ,
753786 place : Place < ' tcx > ,
754787 ) -> Option < ( ) > {
788+ let tcx = self . tcx ;
755789 self . use_ecx ( |this| {
756790 match rvalue {
757791 Rvalue :: BinaryOp ( op, box ( left, right) )
758792 | Rvalue :: CheckedBinaryOp ( op, box ( left, right) ) => {
759793 let l = this. ecx . eval_operand ( left, None ) ;
760794 let r = this. ecx . eval_operand ( right, None ) ;
795+ Self :: check_interpresult ( tcx, & l) ;
796+ Self :: check_interpresult ( tcx, & r) ;
761797
762798 let const_arg = match ( l, r) {
763799 ( Ok ( ref x) , Err ( _) ) | ( Err ( _) , Ok ( ref x) ) => this. ecx . read_immediate ( x) ?,
764800 ( Err ( e) , Err ( _) ) => return Err ( e) ,
765801 ( 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+ ) ;
767806 return Ok ( ( ) ) ;
768807 }
769808 } ;
@@ -799,12 +838,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
799838 }
800839 }
801840 _ => {
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?
803844 }
804845 }
805846 }
806847 _ => {
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?
808851 }
809852 }
810853
0 commit comments