-
-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Support allocation failures when interpreting MIR #86255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Some changes occured to the CTFE / Miri engine cc @rust-lang/miri Some changes occured to the CTFE / Miri engine cc @rust-lang/miri |
|
r? @varkor (rust-highfive has picked a reviewer for you, use r? to override) |
|
The original plan we had for having a memory limit in Miri was to make this a configurable limit. The other two limits (stack size, execution steps) are completely controlled by the interpreter. The idea is that interpretation should be completely deterministic and repeatable. This new error, however, depends on arbitrary factors from the environment: the same evaluation can sometimes succeed, and sometimes fail with |
|
We kind of do have precedent. Consider |
|
r? @oli-obk |
Maybe? I don't know the invariants of the query system well enough. But this can lead to the same CTFE query having different results in different crates. |
oh right. There's no precedent for that. Maybe this should be a fatal error reported directly at the problematic site instead of it being a regular CTFE error? So the query is never left, but instead the compilation is aborted. not sure how to proceed here. cc @rust-lang/compiler It is very easy to make CTFE run out of RAM, thus crashing rustc. Specifically for CTFE we could catch these out of memory situations and report a proper error, but we're unsure of the implications. |
Yeah, that does seem like it could lead to all sorts of issues. From a very quick glance at the PR, it looks like allocation failures in CTFE still result in compilation failing, just with a nicer error message. If compilation still fails, then this seems ok. Are there cases where CTFE will fail but compilation will still succeed? |
Not all CTFE failures are hard errors (yet). So with We could probably do something similar to #86194, and make all resource exhaustion failures always hard errors. |
|
I'm wondering if, even with a hard error, the query system + incremental compilation can get "stuck". We aren't tracking resource exhaustion as an input to the query system, so the query will stay green and not get reevaluated, but loaded from the cache. You may have to remove your cache or modify the right piece of code to get the system "unstuck". |
|
I've made allocation failures a hard error, and it appears that recompiling with more memory available does work, and that the error doesn't get cached, even when forcing incremental compilation with Note that is a lot easier to test this with this diff to make it possible to simulate zero-memory conditions: diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 7405a70d39a..71d09e16ec4 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -125,6 +125,9 @@ pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into<Cow<'a, [u8]>>) ->
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
/// available to the compiler to do so.
pub fn uninit(size: Size, align: Align) -> InterpResult<'static, Self> {
+ if std::env::var(std::ffi::OsStr::new("RUSTC_ALWAYS_FAIL_MIRI_ALLOC")).is_ok() {
+ Err(InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted))?;
+ }
let mut bytes = Vec::new();
bytes.try_reserve(size.bytes_usize()).map_err(|_| {Also note that hard errors currently give a confusing and wrong error message, since there is no differentiation between hard and soft errors in the message generation (EDIT: I opened a PR to fix this: #86340): |
|
That's what I would expect. We only write to the incremental cache when the compilation succeeds so as long compilation always fails eventually when there is an allocation failure, there shouldn't be an issue with the incremental system. |
|
☔ The latest upstream changes (presumably #86291) made this pull request unmergeable. Please resolve the merge conflicts. |
|
☔ The latest upstream changes (presumably #86399) made this pull request unmergeable. Please resolve the merge conflicts. |
|
@bors r+ |
|
📌 Commit 72c38905ce940f3543d9067c5398b3670f1ba01f has been approved by |
|
Delaying a ICE is a great idea, I've gone ahead and implemented it.
This is already done: rust/compiler/rustc_mir/src/transform/const_prop.rs Lines 40 to 43 in 868c702
|
Great! Then making allocation panic immediately (ruling out |
Co-authored-by: Ralf Jung <post@ralfj.de>
|
Thanks for sticking with me through all these rounds of review. :) |
|
📌 Commit d83c46f has been approved by |
|
☀️ Test successful - checks-actions |
This closes #79601 by handling the case where memory allocation fails during MIR interpretation, and translates that failure into an
InterpError. The error message is "tried to allocate more memory than available to compiler" to make it clear that the memory shortage is happening at compile-time by the compiler itself, and that it is not a runtime issue.Now that memory allocation can fail, it would be neat if Miri could simulate low-memory devices to make it easy to see how much memory a Rust program needs.
Note that this breaks Miri because it assumes that allocation can never fail.