Skip to content

Respect the solve polarity for conditions that don't mention the var - #9345

Merged
abadams merged 1 commit into
mainfrom
abadams/fix_solve_for_interval_polarity
Aug 15, 2026
Merged

Respect the solve polarity for conditions that don't mention the var#9345
abadams merged 1 commit into
mainfrom
abadams/fix_solve_for_interval_polarity

Conversation

@abadams

@abadams abadams commented Aug 15, 2026

Copy link
Copy Markdown
Member

solve_for_{inner,outer}_interval track whether they're solving for the region where the condition is true or where it's false, in SolveForInterval::target, which visit(const Not *) flips. The early-out for conditions that don't mention the variable being solved for didn't consult it, so under a negation it returned the two answers the wrong way round.

That inverts the safe direction. Solving

!(((y % 2) != 1) && ((y % 2) != 0))

for x gives an empty outer interval, claiming the condition is nowhere true, when it's a tautology. Written the other way round as

((y % 2) == 0) || ((y % 2) == 1)

there's no Not to flip the polarity, and it correctly gives everything.

…able

solve_for_{inner,outer}_interval track whether they're solving for the region
where the condition is true or where it's false, in SolveForInterval::target,
which visit(const Not *) flips. The early-out for conditions that don't mention
the variable being solved for didn't consult it, so under a negation it
returned the two answers the wrong way round.

That inverts the safe direction. Solving

  !(((y % 2) != 1) && ((y % 2) != 0))

for x gives an empty outer interval, claiming the condition is nowhere true,
when it's a tautology. Written the other way round as

  ((y % 2) == 0) || ((y % 2) == 1)

there's no Not to flip the polarity, and it correctly gives everything.

An empty outer interval is not merely imprecise. TrimNoOps asks for the outer
interval of the condition under which a loop body does something, and deletes
the loop when that comes back empty.

The rest of the class already handles this: fail() widens to everything for an
outer bound and narrows to nothing for an inner one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.05%. Comparing base (6e217f5) to head (adfc085).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9345      +/-   ##
==========================================
+ Coverage   70.01%   70.05%   +0.04%     
==========================================
  Files         258      258              
  Lines       78699    78699              
  Branches    19160    19164       +4     
==========================================
+ Hits        55100    55132      +32     
+ Misses      17881    17872       -9     
+ Partials     5718     5695      -23     

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@abadams
abadams merged commit 4620569 into main Aug 15, 2026
29 of 30 checks passed
@alexreinking
alexreinking deleted the abadams/fix_solve_for_interval_polarity branch August 16, 2026 01:49
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