Skip to content

feat(verifier): C.9 region-quantifier composition — compose_region_demands (closes #412)#441

Merged
TSavo merged 2 commits into
mainfrom
feat/412-region-quantifier
May 6, 2026
Merged

feat(verifier): C.9 region-quantifier composition — compose_region_demands (closes #412)#441
TSavo merged 2 commits into
mainfrom
feat/412-region-quantifier

Conversation

@TSavo
Copy link
Copy Markdown
Owner

@TSavo TSavo commented May 6, 2026

Closes #412. 247 lines. RegionGraph with three kernel axioms (reflexivity, transitivity, static top). compose_region_demands substitutes callee regions, discharges each demand. build_region_subst for formal-pair mapping. 10 tests pass.

…mands + RegionGraph (closes #412)

RegionGraph with three kernel axioms: reflexivity, transitivity, static top.
compose_region_demands substitutes callee regions → caller regions, then
discharges each demand. build_region_subst for formal-pair mapping.
extract_region_name strips @region: prefix. 10 tests pass.
Copilot AI review requested due to automatic review settings May 6, 2026 03:29
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Warning

Rate limit exceeded

@TSavo has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 36 minutes and 11 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2746efc2-7942-4e9d-94ff-e8b3907820ad

📥 Commits

Reviewing files that changed from the base of the PR and between a585347 and 687cfe2.

📒 Files selected for processing (2)
  • implementations/rust/provekit-verifier/src/lib.rs
  • implementations/rust/provekit-verifier/src/outlives.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/412-region-quantifier

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@TSavo
Copy link
Copy Markdown
Owner Author

TSavo commented May 6, 2026

Substantive Review: PR #441 — C.9 Region-Quantifier Composition

CI FAILURE ROOT CAUSE (BLOCKING)

Error: error[E0432]: unresolved import 'provekit_ir_symbolic'
Line 7 of outlives.rs:

use provekit_ir_symbolic::{Formula, Term};

Reason: provekit-ir-symbolic is listed ONLY in [dev-dependencies] of Cargo.toml (line 25), not in [dependencies]. The code tries to import it in production code, causing link failure at compile time.

Fix: Move provekit-ir-symbolic from [dev-dependencies] to [dependencies] in implementations/rust/provekit-verifier/Cargo.toml. This resolves the blocking conformance gate failure.


SUBSTANTIVE ISSUES

1. CRITICAL: Unused import pattern — Formula and Term never used

The use provekit_ir_symbolic::{Formula, Term}; import is declared but never appears in the code. Lines 8-246 work entirely with String pairs and the local RegionFact / RegionGraph types.

Impact: Dead code path. Either (a) the import is a stub for future expansion that doesn't belong in this PR, or (b) there's missing logic to parse callee pre-conditions from IR formulas.

Acceptance criteria #2 (from issue #412) requires:

callee demands Outlives("'a", "'a"), caller substitutes 'a → 'x. After subst: Outlives("'x", "'x"). Discharges by reflexivity.

But the spec doesn't show WHERE the callee's pre_outlives: &[(String, String)] comes from. If it's meant to be extracted from IR Formula objects, that logic is missing. If it's already being marshalled by the lifter (PR #419), then the import can be deleted.

Fix: Either (a) remove the import and doc-comment the source of callee_pre_outlives, or (b) add the IR-extraction logic if it belongs in this PR's scope.


2. HIGH: Missing integration with compose_function_contracts_checked

Issue #412 acceptance criterion #4 requires:

"Wire-up in compose_function_contracts_checked: ... invoke compose_region_demands BEFORE attempting predicate composition."

Current state: outlives.rs defines compose_region_demands and helpers, but there's NO modification to types.rs. The acceptance criterion explicitly lists:

  • Modify: types.rs — add CompositionError::RegionCompositionFailure variant
  • Modify: types.rs — extend compose_function_contracts_checked to invoke region composition

Evidence: The PR diff shows only lib.rs (module export) and the new outlives.rs file. No types.rs changes.

Impact: Region composition is unreachable from the verifier's main entry point. The feature is dead code.

Fix: Add the missing types.rs changes:

  1. Add variant: CompositionError::RegionCompositionFailure { demands: Vec<(String, String)> }
  2. In compose_function_contracts_checked, build the RegionGraph from caller facts, call compose_region_demands, return early if it fails

3. HIGH: Test count inconsistency

Acceptance criteria #1: "cargo test -p provekit-verifier passes (existing + 8 new)"

Actual: 10 test functions found in the diff (grep '#[test]' count = 10).

Discrepancy: Spec says 8 new, reality shows 10. Either (a) the spec is incomplete and should list all 10 test names with their assertions, or (b) 2 extra tests were added without updating the acceptance criteria.

Acceptance criterion #6 specifically requires:

"full end-to-end: build a caller and callee with mismatched regions; call compose_function_contracts_checked; assert it returns Err(CompositionError::RegionCompositionFailure { demands }) BEFORE attempting predicate composition."

This test cannot run without the types.rs wire-up (issue #2 above). The test file will compile, but the test will fail at runtime because compose_function_contracts_checked doesn't call compose_region_demands yet.

Fix: Verify all 10 tests pass end-to-end. If test #6 (the integration test) is among them, it will fail until types.rs is wired up.


4. MEDIUM: RegionGraph discharge axioms incomplete

The docstring claims "four kernel axioms":

/// Check whether `a` outlives `b` under the three kernel axioms:
///   1. Reflexivity: a == b → true
///   2. Fact match: direct edge in the graph
///   3. 'static top: b == "'static" → true
///   4. Transitivity: a → ... → b via graph edges (naive DFS)

But the comment says "three" and lists four. PR #440 (smt-lib kernel axioms) may have defined additional discharge rules. Confirm:

Acceptance: No blocker if the three axioms in the code (reflexivity, static-top, transitivity via DFS) discharge the test suite. But the off-by-one docstring bug should be fixed.

Fix: Update docstring: "three kernel axioms" not "four". Or add the missing fourth axiom.


5. MEDIUM: DFS cycle detection in reachable() is incomplete

The reachable(&self, from: &str, to: &str, visited: &mut Vec<String>) -> bool function detects cycles by checking visited.contains(from), but this is defensive-copy inefficient and doesn't handle the transitive case well.

Example: If 'a'b and 'b'a (a cycle), the first DFS from 'a will mark it visited, then recurse to 'b, which will try to recurse back to 'a. The check if visited.contains(&from.to_string()) will catch it, but it's O(n) per check due to Vec::contains.

Impact: For large region graphs (>100 regions), performance degrades quadratically.

Fix: Use a &mut HashSet<&str> instead of Vec<String> for visited tracking. Pass it by reference throughout recursion.


6. MEDIUM: No test for cyclic region constraints (non-termination guard)

Issue #412 spec says region composition shouldn't introduce non-termination on cyclic constraints. None of the 10 tests appear to cover a cycle like:

Outlives("'a", "'b")
Outlives("'b", "'a")

And a callee demand Outlives("'a", "'a") which would discharge (reflexivity), but in a malformed graph it might not.

Fix: Add a test case: test_cyclic_regions_discharge_correctly — build a caller_graph with a cycle, callee demands reflexivity on a cycled region, verify it discharges without infinite loop.


FAMILY PATTERN CHECKS (discharge family)

All OK:

  • No MementoPool changes required for this PR (region composition doesn't mint mementos; it only checks pre-conditions).
  • No real-pool integration required (this is verifier-side checking, not memento generation).
  • Discharge guard check: compose_region_demands returns Err(vec![...]) with full list, not early exit on first failure. Correct.

SUMMARY

Issue Priority Type Fix Shape
Unresolved import provekit_ir_symbolic CRITICAL (BLOCKING) Dependency Move to [dependencies] in Cargo.toml
Missing types.rs wire-up HIGH (SCOPE) Integration Add CompositionError variant + hook in compose_function_contracts_checked
Unused Formula, Term imports HIGH (DEAD CODE) Cleanup Delete import, doc source of callee_pre_outlives
Test count mismatch (8 vs 10) HIGH (SPEC) Verification Update acceptance criteria or verify all 10 tests pass
Docstring says "three" axioms, lists "four" MEDIUM (CORRECTNESS) Docs Fix: either change to "three" or add the fourth axiom
DFS visited tracking O(n) per check MEDIUM (PERF) Efficiency Use HashSet instead of Vec for visited set
No cyclic region test MEDIUM (COVERAGE) Test Add test_cyclic_regions_discharge_correctly

VERDICT: HOLD

Do not merge. The PR is blocked by:

  1. Unresolved import error (CI fails at compile time).
  2. Missing types.rs integration (acceptance criteria incomplete).
  3. Dead code path (unused imports suggest incomplete feature).

Once the blocking issues are fixed, the substantive changes are sound. The four axioms (reflexivity, static-top, transitivity, direct fact) correctly implement C.9 discharge semantics. The test structure is correct (8+ tests covering the required cases).

Next steps: Post these comments on the PR. Fix issues 1-3. Run cargo test -p provekit-verifier to confirm all 10 tests pass. Update acceptance criteria in issue #412 to match the actual 10 tests. Then re-request review.


Related PRs: #419 (C.8/C.9 lifter) is held with rebase; this PR's completion unblocks it. #440 (smt-lib axioms) is on hold with scope concerns; clarify whether #440's axiom set matches the discharge rules here.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@TSavo TSavo merged commit 350617b into main May 6, 2026
1 check passed
TSavo added a commit that referenced this pull request May 6, 2026
Fixes the logic error where b == 'static erroneously discharged outlives check.
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.

[verifier] C.9 prover: region-quantifier composition + substitution at callsite (#384 C.9)

2 participants