Skip to content

engine: detect self-indexing in subscript polarity analyzer#499

Open
bpowers wants to merge 1 commit intomainfrom
ltm/polarity-subscript-self-index
Open

engine: detect self-indexing in subscript polarity analyzer#499
bpowers wants to merge 1 commit intomainfrom
ltm/polarity-subscript-self-index

Conversation

@bpowers
Copy link
Copy Markdown
Owner

@bpowers bpowers commented May 8, 2026

Summary

The Expr2::Subscript arm in analyze_expr_polarity_with_context
(added in #491) returned current_polarity whenever the array's
identifier matched from_var, without inspecting the index
expressions. For self-indexing patterns like arr[INT(arr[i])],
the relationship between arr and the subscripted value is
non-monotone -- changing arr shifts both the lookup target AND
the index. The arm now walks index expressions via
expr_references_var and returns Unknown when any index
references from_var.

The dominant cases (SUM(arr[*]), arr[Region], indices that
reference other variables) are unaffected -- those indices do not
reference from_var, so the existing behavior of returning
current_polarity is preserved.

Why now

Surfaced by a code review on #491 (the array reducer polarity PR)
after that PR merged. The reviewer flagged it as non-blocking but
worth generalizing because the arm's docstring claimed the case was
fully handled. This PR follows up to make the docstring's claim
true.

Test plan

  • New unit tests covering: literal index, wildcard, var-not-from_var,
    var-from_var (NEW), nested self-indexing (NEW), other-array.
  • Existing polarity / cross-dim tests pass unchanged.
  • cargo clippy --workspace --all-targets -- -D warnings clean
  • cargo fmt --check clean

The Expr2::Subscript arm in analyze_expr_polarity_with_context
returned current_polarity whenever the subscripted array's
identifier matched from_var, regardless of whether the index
expressions also referenced from_var. For arr[INT(arr[i])] (and
similar self-indexing patterns) the relationship is non-monotone:
changing arr shifts both the lookup target and the index. Walk
the index expressions with expr_references_var and return Unknown
when any index also references from_var. The dominant
SUM(arr[*]) / arr[Region] cases are unaffected since their
indices don't reference from_var.

Surfaced by code review on PR #491 after merge.
@bpowers bpowers marked this pull request as ready for review May 8, 2026 16:20
@bpowers
Copy link
Copy Markdown
Owner Author

bpowers commented May 8, 2026

@codex review

@claude
Copy link
Copy Markdown

claude Bot commented May 8, 2026

Review

I reviewed the diff and don't see any blocking issues.

The change is a strict refinement of the prior Subscript arm: when ident == from_var, the indices are now walked for any reference to from_var, returning Unknown if found and current_polarity otherwise. The behavior for non-self-indexing cases (literal indices, wildcards, ranges over constants, indices over other variables) is preserved, so the reducer monotonicity guarantee still carries through for the dominant cases (SUM(arr[*]), arr[Region], etc.).

The inline index match correctly mirrors how expr_references_var (lines 440-450 of the same file) walks IndexExpr2 variants — Expr and Range carry Expr2 and need recursion; Wildcard/StarRange/DimPosition carry no Expr2 so they correctly short-circuit to false. Canonicalization is consistent: expr_references_var checks ident == var || &normalize_module_ref(ident) == var for Var nodes, matching the outer arm's check.

Test coverage exercises literal, wildcard, other-var, direct arr[arr], nested arr[INT(arr[i])], and the other != from_var baseline. A Range-with-from_var case isn't covered, but the implementation is straightforward and the existing coverage demonstrates the contract.

Overall correctness: correct. The patch addresses the docstring-claim gap without altering any pre-existing behavior outside the self-indexing case.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.43%. Comparing base (04614fe) to head (e94ea5d).

Files with missing lines Patch % Lines
src/simlin-engine/src/ltm/polarity.rs 75.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #499      +/-   ##
==========================================
- Coverage   82.44%   82.43%   -0.01%     
==========================================
  Files         243      243              
  Lines       61887    61893       +6     
==========================================
+ Hits        51021    51022       +1     
- Misses      10866    10871       +5     

☔ View full report in Codecov by Sentry.
📢 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.

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.

1 participant