Properly handle const prop failures

This commit is contained in:
Smitty 2021-06-29 20:22:32 -04:00
parent c94bafb69b
commit d04da1125d
4 changed files with 28 additions and 6 deletions

View file

@ -131,11 +131,14 @@ impl<Tag> Allocation<Tag> {
// available to the compiler can change between runs. Normally queries are always // available to the compiler can change between runs. Normally queries are always
// deterministic. However, we can be non-determinstic here because all uses of const // deterministic. However, we can be non-determinstic here because all uses of const
// evaluation do one of: // evaluation do one of:
// - cause a fatal compiler error when they see this error as the result of const // - error on failure
// evaluation // - used for static initalizer evalution
// - panic on evaluation failure // - used for const value evaluation
// - always evaluate very small constants that are practically unlikely to result in // - const prop errors on this since otherwise it would generate different code based
// memory exhaustion // on available memory
// - panic on failure to allocate very small sizes
// - actually panicking won't happen since there wouldn't be enough memory to panic
// - used for caller location evaluation
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
})?; })?;
bytes.resize(size.bytes_usize(), 0); bytes.resize(size.bytes_usize(), 0);

View file

@ -535,4 +535,10 @@ impl InterpError<'_> {
_ => false, _ => false,
} }
} }
/// Did the error originate from volatile conditons such as the memory available to the
/// interpreter?
pub fn is_spurious(&self) -> bool {
matches!(self, InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted))
}
} }

View file

@ -1,6 +1,6 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, InterpResult}; use crate::mir::interpret::{alloc_range, AllocId, Allocation, InterpResult, Pointer, Scalar};
use crate::ty::fold::TypeFoldable; use crate::ty::fold::TypeFoldable;
use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt}; use crate::ty::{self, DefId, SubstsRef, Ty, TyCtxt};
use rustc_ast::Mutability; use rustc_ast::Mutability;

View file

@ -478,6 +478,19 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
Ok(op) => Some(op), Ok(op) => Some(op),
Err(error) => { Err(error) => {
let tcx = self.ecx.tcx.at(c.span); let tcx = self.ecx.tcx.at(c.span);
if error.kind().is_spurious() {
// Spurious errors can't be ignored since otherwise the amount of available
// memory influences the result of optimization and the build. The error
// doesn't need to be fatal since no code will actually be generated anyways.
self.ecx
.tcx
.tcx
.sess
.struct_err("memory exhausted during optimization")
.help("try increasing the amount of memory available to the compiler")
.emit();
return None;
}
let err = ConstEvalErr::new(&self.ecx, error, Some(c.span)); let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
if let Some(lint_root) = self.lint_root(source_info) { if let Some(lint_root) = self.lint_root(source_info) {
let lint_only = match c.literal { let lint_only = match c.literal {