fix(rt): closure aggregate + #setTupleArgs fallback#952
Conversation
dkcumming
left a comment
There was a problem hiding this comment.
Just commenting for now sorry, I need to look closer tomorrow. But just mentioning that the link you sent was from current rust MIR (fine in this case) but for clarity the AggregateKind we are representing is this Stable MIR one. Also I think the assert would be good in the test to see that the data is correctly manipulated
dkcumming
left a comment
There was a problem hiding this comment.
Hesitant to approve without knowing if the change to data.md is mistakenly included or what it relates to. Happy to approve otherwise
| fn repro() -> u8 { | ||
| let f = |x: u8| x + 1; | ||
| apply(f, 41u8) | ||
| } |
There was a problem hiding this comment.
Great example. If you would be open to it in the future it would be nice to use git rebase -i to have the inclusion of the test as the first commit with the expected output failing clearly, then the inclusion of the fix in a following commit, then the update of the test from failing to to passing. It isn't a bit deal but it makes it nice to see the commit history as a story solving the problem. I think #919 is a good example of this.
| andBool isTypedValue(LOCALS[CLOSURE]) | ||
| andBool isRefType(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal))) | ||
| andBool isFunType(#lookupMaybeTy(pointeeTy(lookupTy(tyOfLocal({LOCALS[CLOSURE]}:>TypedLocal))))) | ||
| [priority(46), preserves-definedness] |
There was a problem hiding this comment.
Seems like we are getting some interesting priorities 40, 45 ,46. Maybe not part of this PR but we could do a write up above the rules that explains in relation to the Rust source code and Stable MIR the how the precedence the rules apply
| // Closure-call setup for typed closure environments. | ||
| // When the closure pointee type is known (`typeInfoFunType`), we still need to unpack | ||
| // the second tuple argument into `_2 .. _n` locals. | ||
| rule [setupCalleeClosure3]: <k> #setUpCalleeData( |
There was a problem hiding this comment.
Not sure if there is a way to refactor the 3 rules since they seem very similar. Not worth thinking about right now as this unblocks these closures but we should do some clean up at some point
| rule <k> ARGS:List ~> #mkAggregate(aggregateKindClosure(_CLOSUREDEF, _GENERICARGS)) | ||
| => | ||
| Aggregate(variantIdx(0), ARGS) | ||
| ... | ||
| </k> | ||
|
|
There was a problem hiding this comment.
Is this necessary? It seems unrelated to the test you provided. I removed it and the test passed.
daniel@daniel-MS-7E06 mir-semantics$ git diff
diff --git a/kmir/src/kmir/kdist/mir-semantics/rt/data.md b/kmir/src/kmir/kdist/mir-semantics/rt/data.md
index b47c6fe9..89982d1f 100644
--- a/kmir/src/kmir/kdist/mir-semantics/rt/data.md
+++ b/kmir/src/kmir/kdist/mir-semantics/rt/data.md
@@ -1051,13 +1051,6 @@ Literal arrays are also built using this RValue.
...
</k>
- rule <k> ARGS:List ~> #mkAggregate(aggregateKindClosure(_CLOSUREDEF, _GENERICARGS))
- =>
- Aggregate(variantIdx(0), ARGS)
- ...
- </k>
-
-
// #readOperands accumulates a list of `TypedLocal` values from operands
syntax KItem ::= #readOperands ( Operands )
| #readOperandsAux( List , Operands )
daniel@daniel-MS-7E06 mir-semantics$ make test-integration TEST_ARGS='-k closure-no-capture'
//-snip-
kmir/src/tests/integration/test_integration.py::test_prove_rs[closure-no-capture]
[gw3] [100%] PASSED kmir/src/tests/integration/test_integration.py::test_prove_rs[closure-no-capture]
================================= slowest durations ===================================
39.33s call src/tests/integration/test_integration.py::test_prove_rs[closure-no-capture]
(2 durations < 0.005s hidden. Use -vv to show these durations.)
================================== 1 passed in 40.09s ==================================
daniel@daniel-MS-7E06 mir-semantics$
4e83d3b to
085024d
Compare
|
@dkcumming I refactored the commit history to show each change's meaning. And it shows that there is no need for |
085024d to
a167b02
Compare
- fix(kompile): map linked NormalSym functions to monoItemFn(noBody) [953](#953) - fix(rt): generalize direct-tag enum decoding to any variant count and discriminant [955](#955) - fix(rt): closure aggregate + #setTupleArgs fallback [952](#952) - fix(rt): bug fix for castKindPtrToPtr [974](#974) - fix(rt): repair closure callee setup for iter-eq repro [957](#957)
- fix(rt): handle fun-type closure env refs in callee setup [956](runtimeverification/mir-semantics#956) - fix(decode): accept signed enum tag scalars in _extract_tag [954](runtimeverification/mir-semantics#954) - Added check for FunType in setupCalleeClosure [969](runtimeverification/mir-semantics#969) - Merge in latest master [973](runtimeverification/mir-semantics#973) - fix(kompile): map linked NormalSym functions to monoItemFn(noBody) [953](runtimeverification/mir-semantics#953) - fix(rt): generalize direct-tag enum decoding to any variant count and discriminant [955](runtimeverification/mir-semantics#955) - fix(spl-token): encode multisig signers as pubkey aggregates [958](runtimeverification/mir-semantics#958) - fix(rt): closure aggregate + #setTupleArgs fallback [952](runtimeverification/mir-semantics#952) - fix(rt): bug fix for castKindPtrToPtr [974](runtimeverification/mir-semantics#974) - fix(rt): repair closure callee setup for iter-eq repro [957](runtimeverification/mir-semantics#957) - Change the number of signers from 11 to 3 [982](runtimeverification/mir-semantics#982) - Merging latest master into feature/p-token [981](runtimeverification/mir-semantics#981)
Summary
Add three semantics fixes needed by the closure-call path, plus a regression test:
aggregateKindClosurereduction:ARGS:List ~> #mkAggregate(aggregateKindClosure(...)) => Aggregate(variantIdx(0), ARGS)#setTupleArgs(IDX, VAL:Value) [owise]fallback for unwrapped single-value argumentssetupCalleeClosure3(withisFunTypepredicate)closure-no-capture.rsregression testContext
Stable MIR represents closure construction via
Rvalue::Aggregate(AggregateKind::Closure(...)). The K semantics had rules for tuple/ADT aggregates, but no rule foraggregateKindClosure.For closure calls, argument placement goes through
#setTupleArgs. Existing rules only handled tuple/list-shaped payloads.Also, once closure type metadata is present, closure env locals can be typed as
Ref<FunType(...)>. Before this PR, closure setup rules only matchedVoidType-based closure typing paths, so the typed closure path needed an explicit setup rule.Red vs Green for
aggregateKindClosureRED:
No matching rule, execution is stuck.
GREEN:
aggregateKindClosurereduces toAggregate(variantIdx(0), ARGS), so closure aggregate construction proceeds.Red vs Green for
#setTupleArgs [owise]After closure aggregate reduction is added, execution advances to the next blocker:
RED (next blocker):
No existing
#setTupleArgsrule matches this plainValueshape.GREEN:
The fallback
handles the unwrapped single-value case and allows argument setup to continue.
Red vs Green for
setupCalleeClosure3With typed closure metadata, closure env can appear as
Ref<FunType(...)>. Existing closure setup rules were guarded forVoidTypeclosure typing paths, so typed closure setup could miss those rules.RED:
Typed closure env path does not satisfy the existing
VoidTypeguard shape for closure setup, so closure-call setup does not reliably take the typed closure path.GREEN:
setupCalleeClosure3adds the typed path explicitly:isFunType(#lookupMaybeTy(pointeeTy(...)))#setTupleArgs(2, getValue(LOCALS, TUPLE))This keeps closure-call argument placement consistent when closure env typing is known.
Proof evidence
Without fix (RED):
closure-no-capture.rsgets stuck on closure aggregate, and after adding only the closure aggregate rule it gets stuck at#setTupleArgs(2, Integer(41,8,false)).With fix (GREEN):
Test plan
test_prove_rs[closure-no-capture]make test-integrationregression