Repository navigation
fix(mir-importer): preserve non-terminating drops - #1361
Merged
Merged
Conversation
Signed-off-by: Yunus Mutlu <mutluyunus708@gmail.com>
YunusMutlu
force-pushed
the
fix/drop-noop-termination
branch
from
October 13, 2026 12:05
ccc6877 to
80c4568
Compare
…converging control verify-code-shape.sh now reads drop_glue.ll as well as drop_glue.ptx. For the two diverging probes it requires the kernel body to keep the call to their drop glue, which is the decision the importer owns; the PTX checks stay and say they rely on opt inlining the glue because noinline is not propagated. A missing artifact is named instead of a silent exit. A third compile-only kernel, reconverging_drop_probe, drops an effect-free destructor whose if/else branches join back together. The script requires no glue call in its kernel body and both of its stores in the PTX, so a regression to "any revisit fails the proof" cannot pass. Its post-drop store uses a second slot so dead-store elimination cannot remove the first one. The README documents the three probes and runs its commands from the cuda-oxide repository root. Signed-off-by: nihalpasham <nihalp@nvidia.com>
The drop_glue module doc described the proof as purely effect-based. It now says the glue must also return: a reachable control-flow cycle, or a call back into an instance already under proof, fails it even when every statement is harmless, because erasing a call that may never return would let the code after the drop execute. STATUS.md states the contract as "proven unobservable and terminating, or its call is emitted", and no longer lists slice element drops among the glue that still fails compilation, since [T; N] element glue for a plain Drop type now translates. Signed-off-by: nihalpasham <nihalp@nvidia.com>
A one-page figure for the book and the pull request, in the style of the tile-libraries direct-linkage figure. Signed-off-by: nihalpasham <nihalp@nvidia.com>
Collaborator
|
/ok to test 4efe8ba |
Collaborator
|
Thanks, this is the right fix: the proof was erasing a destructor call it never proved returns, and the one predicate all four call sites share is where the rule belongs. Three small things on top:
At |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
The importer erases a destructor call when its no-op proof says the destructor does nothing visible. The proof never asked whether the destructor returns, so a
Dropthat loops forever, or recurses into itself, was deleted and the kernel ran on past it. The proof is now a three-state depth-first walk: a reachable cycle, or a call back into an instance already under proof, fails it and the call stays.What we fixed
LoopingDropandRecursiveDropkeep their glue call. A reconvergingif/elsedestructor is still proven harmless and erased.drop_glueexample asserts the importer's own decision in the pre-optdrop_glue.ll(the glue call present for the diverging probes, absent for the control) and keeps the PTX checks.Implementation
drop_glue.rs: the proof tracks Unseen, InProgress and Proven per block and per instance. A successor that is still InProgress is a back edge; a Proven one is a join. The same rule covers a call back into a destructor already under proof.Dropterminator, explicitdrop_in_placeelision, the collector and device codegen) share it, so there is no copied policy.diverging_cfg_drop_probe,diverging_recursive_drop_probeand the newreconverging_drop_probe, all compile-only, checked byverify-code-shape.sh.Verification
Checked at
4efe8baf7(nightly-2026-10-11, RTX 5090):cargo test -p mir-importer --all-targets, clippy and rustdoc with warnings as errors, fmt, the example's fmt and clippy gates, the 18 repository guards and the lock check: clean.drop_gluesource built with main's backend failsverify-code-shape.sh(no glue call, store A gone); this branch passes on the pre-opt IR and the PTX.cargo oxide run drop_glue:SUCCESS, 8 PASS, memcheck clean.array_for_loop, acyclic diamonds and theassert_uncheckedpath keep per-kernel identical PTX.Drop,Optionof a hanging type, a loop behind a runtimeif,mem::drop, closures and a diamond followed by a loop are all kept.Caveats
cannot compute in-memory address for dropped place) on both backends. It now fails closed instead of being erased silently. Separate issue.Closes #1360.