Skip to content

fix(rt): closure type metadata decode + setupCalleeClosure3#957

Draft
Stevengre wants to merge 5 commits intomasterfrom
jh/fix-closure-type-call-setup
Draft

fix(rt): closure type metadata decode + setupCalleeClosure3#957
Stevengre wants to merge 5 commits intomasterfrom
jh/fix-closure-type-call-setup

Conversation

@Stevengre
Copy link
Contributor

@Stevengre Stevengre commented Feb 28, 2026

Summary

Add support for typed closure environments in the call setup path, and clean up the Span parameter threading.

  • Add zero-sized typeInfoFunType constant decode rule (data.md)
  • Add setupCalleeClosure3 rule for closures whose pointee type resolves to typeInfoFunType (kmir.md)
  • Add isFunType function declaration and rules
  • Fix isTypedLocalisTypedValue guards on existing setupCalleeClosure rules
  • Add #setLocalValue for closure environment initialization in all setupCalleeClosure rules
  • Remove unused Span parameter from #execTerminatorCall, #setUpCalleeData, and #execIntrinsic (cleanup)
  • Add iter-eq-copied-take-dereftruncate-fail.rs test

Context

When stable-mir-json records closure type metadata (via the companion PR stable-mir-json#129), the closure's Ty entry appears in the type table as typeInfoFunType(...). The existing setupCalleeClosure rules only matched when the closure pointee type was typeInfoVoidType (missing from type table) — with proper metadata present, no rule matched and call setup got stuck.

The fix adds setupCalleeClosure3 at priority 46 that matches when isFunType(#lookupMaybeTy(pointeeTy(...))) is true. This follows the same pattern as existing rules but handles the case where type metadata is available.

The isTypedLocalisTypedValue fix is necessary because closure locals may be newLocal(...) (reserved but not yet assigned), and isTypedLocal requires a fully typed value. isTypedValue is the correct check since it matches both initialized typed values and newLocal entries.

Additionally, the existing rules did not initialize local _1 (the closure environment). Rustc's calling convention places the closure environment in _1 and the argument tuple in _2. The fix adds #setLocalValue(place(local(1), ...), ...) before #setTupleArgs.

The Span parameter removal is a cleanup — Span was threaded through #execTerminatorCall#setUpCalleeData#execIntrinsic but never used in any rule body. Removing it simplifies the signatures.

Without this fix (after stable-mir-json provides closure types), closure calls get stuck:

Leaf <k>:
  #setUpCalleeData(monoItemFn(...), operandMove(...) operandMove(...) .Operands)
  # no setupCalleeClosure rule matches — closure pointee is typeInfoFunType, not typeInfoVoidType

With this fix, setupCalleeClosure3 matches and the closure call proceeds correctly.

Note: The new setupCalleeClosure3 rule is safe dead code until stable-mir-json#129 is merged and the submodule is bumped. Without the submodule bump, closure types remain typeInfoVoidType and the existing rules handle them.

Related PRs

Test plan

  • -fail test (proof advances further)
  • make test-integration regression
  • New rules fully exercised after stable-mir-json submodule bump

… closures

stable-mir-json wasn't recording closure Ty entries in the type table,
so zero-sized closure constants decoded to thunks. Additionally, the
existing setupCalleeClosure rules didn't handle the case where the
closure pointee type resolves to a known typeInfoFunType (as opposed
to typeInfoVoidType).

Changes:
- Add zero-sized typeInfoFunType constant decode rule (data.md)
- Add setupCalleeClosure3 rule for typed closure environments (kmir.md)
- Add isFunType function declaration and rules
- Fix isTypedLocal -> isTypedValue guards on existing closure rules
- Add #setLocalValue for closure environment in all setupCalleeClosure rules
- Remove unused Span parameter from #execTerminatorCall, #setUpCalleeData,
  and #execIntrinsic signatures (cleanup, no behavior change)

Test: iter-eq-copied-take-dereftruncate-fail.rs

Note: The new setupCalleeClosure3 rule requires a stable-mir-json
submodule bump (separate PR) to be exercised at runtime.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant