Skip to content

fix(rt): handle zero-sized function types in decode and ZST recognition#813

Merged
automergerpr-permission-manager[bot] merged 4 commits intomasterfrom
jh/zero-sized-decode
Mar 28, 2026
Merged

fix(rt): handle zero-sized function types in decode and ZST recognition#813
automergerpr-permission-manager[bot] merged 4 commits intomasterfrom
jh/zero-sized-decode

Conversation

@Stevengre
Copy link
Copy Markdown
Contributor

@Stevengre Stevengre commented Nov 7, 2025

Summary

Fix two issues preventing correct handling of zero-sized function item types (e.g., non-capturing closures):

  1. #zeroSizedType did not recognize typeInfoFunType (types.md)
    — Function items are inherently zero-sized (#elemSize already returns 0), but #zeroSizedType returned false, preventing rvalueRef from materializing uninitialized closure locals.

  2. #decodeConstant had no rule for typeInfoFunType (data.md)
    — Zero-sized function constants fell through to the thunk wrapper instead of decoding to Aggregate(variantIdx(0), .List).

Evidence

closure-staged.rs with terminate-on-thunk:

Steps Result
Before 44 thunk(#decodeConstant(constantKindZeroSized, _, typeInfoFunType(_)))
After 266 #EndProgram

@Stevengre Stevengre marked this pull request as ready for review November 7, 2025 05:25
@Stevengre Stevengre self-assigned this Nov 7, 2025
@Stevengre Stevengre marked this pull request as draft November 14, 2025 05:05
@Stevengre Stevengre force-pushed the jh/zero-sized-decode branch 4 times, most recently from 6f0c0b9 to 3de1980 Compare March 23, 2026 12:42
Stevengre and others added 3 commits March 26, 2026 02:59
Rename closure-staged.rs → closure-staged-fail.rs and enable
terminate-on-thunk for this test. Without a #decodeConstant rule for
typeInfoFunType, the non-capturing closure passed as a constant operand
cannot be decoded and falls through to a thunk:

  Node 3: #decodeConstant(constantKindZeroSized, ty(33), typeInfoFunType("..."))
  Node 4: thunk(#decodeConstant(...))  ← proof terminates here

Also adds PROVE_TERMINATE_ON_THUNK list to test_integration.py for
per-test thunk termination control.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two fixes for zero-sized function item types (closures without captures):

1. types.md: Add #zeroSizedType(typeInfoFunType(_)) => true
   Function items are inherently zero-sized (#elemSize already returns 0),
   but #zeroSizedType did not recognize them. This prevented rvalueRef
   from materializing uninitialized zero-sized closure locals.

2. data.md: Add #decodeConstant rule for typeInfoFunType
   Zero-sized function constants decode to Aggregate(variantIdx(0), .List),
   matching the existing treatment of zero-sized structs and tuples.

RED → GREEN for closure-staged (with terminate-on-thunk):
  Before: 44 steps → thunk(#decodeConstant(constantKindZeroSized, _,
          typeInfoFunType(_))) — proof terminated on thunk
  After:  266 steps → #EndProgram — proof passes, no thunks

Renames closure-staged-fail.rs back to closure-staged.rs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The expected output was only needed to show the RED → GREEN transition
in the commit history. Now that the fix is in place, closure-staged
passes as a normal prove test without needing show output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Stevengre Stevengre force-pushed the jh/zero-sized-decode branch from 3de1980 to 3aa012d Compare March 26, 2026 03:01
@Stevengre Stevengre marked this pull request as ready for review March 26, 2026 03:02
@Stevengre Stevengre requested a review from mariaKt March 26, 2026 03:02
@Stevengre Stevengre changed the title fix(rt): Handle zero sized function constant decode fix(rt): handle zero-sized function types in decode and ZST recognition Mar 26, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3aa012d252

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

rule #zeroSizedType(typeInfoVoidType) => true
// FIXME: Only unit tuples, empty structs, and void are recognized here; other
// zero-sized types (e.g. single-variant enums, function or closure items,
rule #zeroSizedType(typeInfoFunType(_)) => true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude invalid lookup sentinel from ZST function rule

#zeroSizedType(typeInfoFunType(_)) => true now also matches the sentinel returned by lookupTy on missing entries (typeInfoFunType(" ** INVALID LOOKUP CALL **") in rt/value.md), so unresolved type IDs are silently treated as zero-sized. That changes behavior in places that gate on #zeroSizedType (notably pointer projection compatibility in #pointeeProjection and zero-sized local materialization in rvalueRef), allowing execution to proceed with fabricated ZST behavior instead of surfacing a missing-type-table condition; this can corrupt proof behavior when type extraction is incomplete.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

@jberthold jberthold left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
CI hits a timeout (20 minutes) , could it be caused by the change?

Copy link
Copy Markdown
Collaborator

@dkcumming dkcumming left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I think it is fine to add --terminate-on-thunk specifically for this for now. But that it had to be added to see that we were not decoding these functions in the test suite indicates to me we should add --terminate-on-thunk to all the tests (something I have been thinking for some time now). This will probably create a regression but it will also show us clearly what we are not handling. That time might not be now to swap but it would be good to understand how many tests regress with this.

@automergerpr-permission-manager automergerpr-permission-manager bot merged commit 9af0261 into master Mar 28, 2026
17 of 22 checks passed
@automergerpr-permission-manager automergerpr-permission-manager bot deleted the jh/zero-sized-decode branch March 28, 2026 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants