Skip to content

Take the precondition of the entry block from the signature - #226

Draft
coord-e wants to merge 1 commit into
mainfrom
claude/entry-precondition-from-signature
Draft

Take the precondition of the entry block from the signature#226
coord-e wants to merge 1 commit into
mainfrom
claude/entry-precondition-from-signature

Conversation

@coord-e

@coord-e coord-e commented Aug 16, 2026

Copy link
Copy Markdown
Owner

First of three, each removing one predicate variable that stood for a fact the constraints already state elsewhere. The other two build on this one: #227 (the type of a call) and #224 (the state at a join).

The entry block took a template for its precondition, which assert_entry then bounded from below by the precondition of the function. Nothing else constrained it, so the predicate variable stood for the precondition of the function and nothing more. It is installed directly instead, equating each parameter with the value it has on entry (BasicBlockTypeParamKind::OuterFnParam), which is what the least solution of the removed predicate variable gave.

The parameter types now come from the signature as well (install_signature_types). Once assert_entry is gone, a refinement written in the signature has nowhere else to reach the block from: a refinement nested in a type (Vec<{ v: i32 | v > 0 }>) would be dropped, and the contract of a function-typed parameter would be replaced by a fresh, unconstrained predicate variable that a solver may read as false — unsound. tests/ui/pass/fn_ptr.rs and tests/ui/pass/refine_param_*.rs cover both.

assert_entry and what only it used (relate_sub_param_types, truncate_outer_fn_params, drop_bb_zst_params, drop_unused_expected_params) go with it.

Effect

Over tests/ui/pass (160 files), predicate variables generated: 1691 → 1293.

Notes for review

Two steps carry the soundness of this change and are worth a second pair of eyes:

  • the equation between each parameter and its OuterFnParam copy in entry_precondition — without it the postcondition of a function loses its footing on the entry values;
  • install_signature_types, per the paragraph above; its absence fails loudly for a nested refinement but silently and unsoundly for a function-typed parameter.

316 tests pass.

The entry block took a template for its precondition, which
`assert_entry` then bounded from below by the precondition of the
function. Install the precondition of the function directly, equating
each parameter with the value it has on entry, which is what the
predicate variable stood for.

The parameter types come from the signature as well, so that refinements
written in it reach the block: a refinement nested in a type
(`Vec<{ v: i32 | v > 0 }>`) or the contract of a function-typed
parameter has nowhere else to come from once `assert_entry` is gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7MyQbvfkfNy1h7yeN553N
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