Skip to content

Prove a generic owned conversion against byte models - #3884

Open
joshlf wants to merge 1 commit into
Gdtlvwakxpzsmcwa7vhtmv7d5h63sbw3lfrom
Gmhd5pbk4jan7lwabm442fdhchwui6nnr
Open

joshlf wants to merge 1 commit into
Gdtlvwakxpzsmcwa7vhtmv7d5h63sbw3lfrom
Gmhd5pbk4jan7lwabm442fdhchwui6nnr

Conversation

@joshlf

@joshlf joshlf commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Add a trait-bounded const helper that consumes Src: IntoBytes and returns
Dst: FromBytes after an equal-size post-monomorphization assertion. Use
ManuallyDrop and the standard transmute_copy operation. Their Lean
interpretations retain the original extracted arguments before adding
semantic providers. The helper requires Rust 1.83 to borrow a generic
source that may have interior mutability in const evaluation. The production
transmute macro remains unchanged.

Interpret the copy through both physical decoders and destination model
admission. Quantify generic proofs over a checked representation preference,
then prove coverage of every represented output while fixing the decoders.
This preserves ambiguous source encodings. Admission limits the fragment
to one conversion with polymorphic forwarding; independent choices across
repeated operations require a richer effect model.

Audit original compiler endpoints, constant initializers, exact retained
providers, and complete primitive interpretations. Preserve the ordinary
ABI size queries and state physical-width correspondence explicitly. The
existing ownership checker proves the erased conditional drops empty.

Prove the actual helper and a caller that reuses its theorem. Add independent
contract expectations and compiled mutation controls for substituted
providers, altered primitive models, missing call witnesses, and the size
guard. Physical profiles and standard-library semantics remain explicit
Rust correspondence premises; this adds no general pointer/resource model.

Regenerate UI snapshots on all three pinned compilers for the shifted
source line numbers. Their diagnostic text is unchanged.

Authored by an AI agent acting on joshlf's behalf.


Latest Update: v6 — Compare vs v5

📚 Full Patch History

Links show the diff between the row version and the column version.

Version v5 v4 v3 v2 v1 Base
v6 vs v5 vs v4 vs v3 vs v2 vs v1 vs Base
v5 vs v4 vs v3 vs v2 vs v1 vs Base
v4 vs v3 vs v2 vs v1 vs Base
v3 vs v2 vs v1 vs Base
v2 vs v1 vs Base
v1 vs Base
⬇️ Download this PR

Branch

git fetch origin refs/heads/Gmhd5pbk4jan7lwabm442fdhchwui6nnr && git checkout -b pr-Gmhd5pbk4jan7lwabm442fdhchwui6nnr FETCH_HEAD

Checkout

git fetch origin refs/heads/Gmhd5pbk4jan7lwabm442fdhchwui6nnr && git checkout FETCH_HEAD

Cherry Pick

git fetch origin refs/heads/Gmhd5pbk4jan7lwabm442fdhchwui6nnr && git cherry-pick FETCH_HEAD

Pull

git pull origin refs/heads/Gmhd5pbk4jan7lwabm442fdhchwui6nnr

Stacked PRs enabled by GHerrit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T16:28:30.719763Z f2aa9ee PR opened
🔒 Security Review ✅ Completed 2026-10-15T16:30:46.126140Z f2aa9ee PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@codecov-commenter

codecov-commenter commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.89%. Comparing base (633fe56) to head (a11d390).

Files with missing lines Patch % Lines
zerocopy/src/util/macro_util.rs 0.00% 5 Missing ⚠️
zerocopy/src/util/generic_transmute.rs 0.00% 3 Missing ⚠️
Additional details and impacted files
@@                          Coverage Diff                          @@
##           Gdtlvwakxpzsmcwa7vhtmv7d5h63sbw3l    #3884      +/-   ##
=====================================================================
+ Coverage                              48.80%   48.89%   +0.08%     
=====================================================================
  Files                                     33       34       +1     
  Lines                                   4725     4733       +8     
=====================================================================
+ Hits                                    2306     2314       +8     
  Misses                                  2419     2419              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces generic owned conversions through transmute_copy in zerocopy along with formal verification models, proofs, and audits in Lean and Python (Aeneas) to verify their safety. The review feedback highlights three key issues in the Aeneas admission checker (admission.py): a crash when processing on_unwind in unstructured control flow blocks due to unhandled variant options, a false positive in the transmute-copy closure audit caused by duplicate recording of global constant initializers, and potential runtime overhead/dependency issues from using re.fullmatch instead of basic string operations for type variable validation.

Comment on lines +1191 to +1192
elif tag in {'Call', 'Drop', 'Assert'}:
children = [term['target'], term['on_unwind']]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

critical

In Charon, on_unwind is an Option<BlockId> represented as a variant (e.g., {"None": []} or {"Some": block_id}). Passing it directly to children causes type(child) is not int to evaluate to True, which raises a ValueError and crashes the audit for any unstructured function containing a Call, Drop, or Assert terminator. Unpack the on_unwind option using variant to extract the actual block index when it is Some.

Suggested change
elif tag in {'Call', 'Drop', 'Assert'}:
children = [term['target'], term['on_unwind']]
elif tag in {'Call', 'Drop', 'Assert'}:
children = [term['target']]
if term.get('on_unwind'):
unwind_tag, unwind_val = variant(term['on_unwind'])
if unwind_tag == 'Some':
children.append(unwind_val)

Comment on lines +536 to +541
if tag == 'Call':
function, _ = producer
kind, callee = variant(function['kind'])
if kind != 'Fun':
raise ValueError('Unresolved global initializer')
self.record_native_call(callee, arguments, kind='global')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

When a global constant is referenced multiple times within the same function, global_value is called multiple times. Since record_native_call is called before checking if index in self.globals:, it records duplicate calls from the current function to the global's initializer. This causes duplicate edges in edges, which leads count(owner) to sum the same child multiple times and falsely raise ValueError('Transmute-copy closure contains multiple byte choices'). Prevent duplicate recording by checking if the call has already been recorded for the current caller.

Suggested change
if tag == 'Call':
function, _ = producer
kind, callee = variant(function['kind'])
if kind != 'Fun':
raise ValueError('Unresolved global initializer')
self.record_native_call(callee, arguments, kind='global')
if tag == 'Call':
function, _ = producer
kind, callee = variant(function['kind'])
if kind != 'Fun':
raise ValueError('Unresolved global initializer')
if not any(row.get('caller_def_id') == self.current_function['def_id'] and
row.get('callee_def_id') == callee and
row.get('kind') == 'global'
for row in self.calls):
self.record_native_call(callee, arguments, kind='global')

Comment on lines +1144 to +1147
if not isinstance(arguments, list) or not arguments or any(
not isinstance(argument, str) or
(match := re.fullmatch(r'T(0|[1-9][0-9]*)', argument)) is None or
int(match[1]) not in source_indices for argument in arguments):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using re.fullmatch introduces regex overhead and a potential runtime dependency on the re module if it is not imported in admission.py. Since Charon type variables are always named T0, T1, etc., we can simplify this check using basic string operations (startswith and isdigit), which is both safer and more efficient.

Suggested change
if not isinstance(arguments, list) or not arguments or any(
not isinstance(argument, str) or
(match := re.fullmatch(r'T(0|[1-9][0-9]*)', argument)) is None or
int(match[1]) not in source_indices for argument in arguments):
if not isinstance(arguments, list) or not arguments or any(
not isinstance(argument, str) or
not argument.startswith('T') or
not argument[1:].isdigit() or
int(argument[1:]) not in source_indices for argument in arguments):

Add a trait-bounded const helper that consumes Src: IntoBytes and returns
Dst: FromBytes after an equal-size post-monomorphization assertion. Use
ManuallyDrop and the standard transmute_copy operation. Their Lean
interpretations retain the original extracted arguments before adding
semantic providers. The helper requires Rust 1.83 to borrow a generic
source that may have interior mutability in const evaluation. The production
transmute macro remains unchanged.

Interpret the copy through both physical decoders and destination model
admission. Quantify generic proofs over a checked representation preference,
then prove coverage of every represented output while fixing the decoders.
This preserves ambiguous source encodings. Admission limits the fragment
to one conversion with polymorphic forwarding; independent choices across
repeated operations require a richer effect model.

Audit original compiler endpoints, constant initializers, exact retained
providers, and complete primitive interpretations. Preserve the ordinary
ABI size queries and state physical-width correspondence explicitly. The
existing ownership checker proves the erased conditional drops empty.

Prove the actual helper and a caller that reuses its theorem. Add independent
contract expectations and compiled mutation controls for substituted
providers, altered primitive models, missing call witnesses, and the size
guard. Physical profiles and standard-library semantics remain explicit
Rust correspondence premises; this adds no general pointer/resource model.

Regenerate UI snapshots on all three pinned compilers for the shifted
source line numbers. Their diagnostic text is unchanged.

gherrit-pr-id: Gmhd5pbk4jan7lwabm442fdhchwui6nnr
Agent-authored-by: AI agent acting on joshlf's behalf

This branch has not been deployed

No deployments
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.

2 participants