Properly handle const prop failures
This commit is contained in:
parent
c94bafb69b
commit
d04da1125d
4 changed files with 28 additions and 6 deletions
|
@ -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);
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue