Repository navigation
Fold a state error's Found under the constants its path conditions state - #529
CatarinaGamboa wants to merge 2 commits into
Conversation
The conditions of the conditional facts of a state error's Found are written with c for x wherever Found states x == c, for a literal or an enum constant, and folded; a branch is dropped only when its condition folds to a constant that rules it out. Found stays equivalent, and the fact x == c stays. A1_09's nested if-then-else becomes newMode == BORDERLESS && (previousMode != BORDERLESS ? ... : ...). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clean-code reviewI audited the diff with the clean-code-principles checklist. Fixed, while writing it:
Declined:
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex review, round 1
Soundness prompt. It found a real gap. Once a fold removes the last condition that mentions
The shorter headline is still a fact the verifier knew (S1), but the path condition that explains the branch disappears. That is not "folded under the shown path condition". Fixed in "Keep a state Found unfolded when folding would hide a fact it showed".
Tests: 730 run, 0 failures. |
Codex review, round 2Soundness prompt. Eight new programs, built and compared with
Declined for this PR. It is the round 1 fix working as designed: when keeping a fold would hide the path fact, we show the unfolded Found, which is sound and complete. Keeping a settled path fact visible needs This ends the Codex loop for this PR: nothing relevant is left. |
Closes #522, part 5 of 5: A1_09's nested if-then-else Found, folded under the shown path condition. Design: #522 (comment)
What it does
A new pass,
VCPathFolding, runs once on the shown Found of a state error, afterVCRelevantFacts:It collects the facts
x == cthat the chain states.cis a literal (int, long, real, boolean, char), anEnumnode, or a Java enum constant. A Java enum constant enters the VC as a variable namedType.CONST; it counts as a constant only when the unsimplified chain binds it with an enum type that declares that constant.In the conditions of the chain's if-then-else facts, it writes
cforx. It then folds the condition with the existingVCFolding/VCLogicalSimplification, plusA == B/A != Bbetween two such enum constants (distinct values of a datatype).A branch is dropped only when its condition folds to
trueorfalse. Otherwise the ITE stays, with its simplified condition. No SMT check is used.VCCheckerkeeps the fold only if every fact of the unfolded shown Found that has no if-then-else is still shown. Otherwise, when a settled branch would make the headline drop the path fact that chose it (mode == A), it shows the unfolded Found.Why it is sound: every fact of the premise chain holds wherever the others are checked. Writing
cforxwherex == cis a premise keeps Found equivalent, and the factx == citself stays. The chain the pass gets has no Expected node (joinPredicatesclones it before appending Expected), so nothing is assumed from Expected.The pass is a normal simplification step ("Path Folding"), so the panel's steps can show it.
A1_09, before and after
otherwiseleft to the panel rows (extension side).reportedLine.Test
TestFoundBinders.stateFoundFoldsTheBranchesItsPathConditionRulesOut, on a new fixture shaped like A1_09:ErrorStatePathFolding.java, an enum mode with a two-arm if/else-if and a switch case. No existing fixture has a path-condition constant inside an ITE. The test fails without the change.mvn test: 730 run, 0 failures.Conflicts
VCChecker.throwStateRefinementError(whereshownis computed). The From-note PRs (Origin note: say where the wrong state of a receiver comes from #528) and Show a counterexample for state errors, restricted to the shown Found #527 change the lines just after it, so whichever merges second needs a trivial rebase.🤖 Generated with Claude Code