fix(rt): resolve thunk(operandCopy) in projection traversal#956
Draft
fix(rt): resolve thunk(operandCopy) in projection traversal#956
Conversation
…w creation
When a value is thunked as thunk(operandCopy(place(...))), projection
traversal and borrow creation had no rules to resolve the thunk, causing
stuck #traverseProjection ~> #readProjection / #forRef terms.
Add #isThunkOperandCopy predicate and four #traverseProjection rules
that compose remaining projections onto the thunked place and delegate
to existing operand evaluation:
- Copy-read: resolve to operandCopy with composed place
- Move-read: emit #writeMoved then resolve the copy
- Write: delegate to #setLocalValue on composed place
- Borrow (#forRef): materialize #mkRef directly to avoid re-traversal
Guard existing .ProjectionElems terminal rules with
notBool #isThunkOperandCopy(VAL) to prevent premature matching.
Tests: iter-copied-take-next-thunk-fail.rs,
iter-map-eq-copied-take-thunk-fail.rs
3 tasks
Add a rule for `aggregateKindClosure` to construct closures as `Aggregate(variantIdx(0), ARGS)`, matching the existing tuple and ADT aggregate handling. Add an `[owise]` fallback to `#setTupleArgs` for `Value` arguments that are not wrapped in an `Aggregate` tuple. This handles closure-call paths where a single argument is passed directly. Test: `closure-no-capture.rs` — a non-capturing closure passed through a generic `FnOnce` call. Exercises the `#setTupleArgs` fallback for unwrapped single-value arguments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
Summary
Add rules to resolve
thunk(operandCopy(place(...)))values during projection traversal and borrow creation. Guard existing terminal rules to prevent premature matching on thunked values.#isThunkOperandCopypredicate#traverseProjectionrules for thunked copy-places (read, move-read, write, borrow).ProjectionElemsterminal rules withnotBool #isThunkOperandCopy(VAL)iter-copied-take-next-thunk-fail.rsanditer-map-eq-copied-take-thunk-fail.rstestsContext
When closure or iterator type metadata is incomplete (e.g. missing from the SMIR type table), zero-sized constants are decoded as
thunk(operandCopy(place(...)))instead of concrete values. When downstream code projects into such a thunked value — via field access, deref, or borrow creation — the#traverseProjectionrules had no matching case, leaving the term stuck.The fix composes remaining projections onto the thunked place and delegates to existing operand evaluation:
=> operandCopy(place(local(I), appendP(PLACEPROJ, PROJS)))— re-evaluates the original place with composed projections#writeMovedthen resolves as copy#setLocalValueon the composed place#forRef): materializes#mkRefdirectly to avoid re-traversal (re-entering viagetValue(LOCALS, I)can reintroduce the same thunk, causing non-terminating projection growth)This is a workaround for incomplete type metadata — miri does not have thunks since it always has complete type information. PR #957 (closure type metadata) addresses the root cause by providing the missing type info, but this PR handles thunks that still arise in other scenarios.
Without this fix, iterator patterns like
keys.iter().take(n).copied()get stuck:With this fix, the thunked place is composed and re-evaluated, allowing execution to continue.
Proof evidence
Without fix (RED):
spl-multisig-iter-eq-copied-next-fail.rsgets stuck at#traverseProjection ~> #forRefWith fix (GREEN): Execution advances past the thunk-projection point (test still fails at a later point due to other unrelated issues, hence the
-failsuffix).Test plan
-failtests (proof advances further with fix, still fails at later point)make test-integrationregression