Skip to content

fix(compiler): propagate OOB failures through collector cell expressions #88

Description

@thiremani

Summary

An out-of-bounds array access inside a compound collector cell is currently materialized as zero before the surrounding expression completes. This lets arithmetic continue with fabricated data instead of propagating the missing outcome to the collector boundary.

Reproduction

arr = [3 1 4 1 5 9 2 6]
i = 0:8

diff = [arr[i + 1] - arr[i]]
"Diff: -diff"

Current output:

Diff: [-2 3 -3 4 4 -7 4 -6]

Expected output:

Diff: [-2 3 -3 4 4 -7 4 0]

0:8 drives i = 0..7. At i = 7, arr[i + 1] is out of bounds. That access should yield nothing, the failure should propagate through the subtraction, and the collector should zero-fill the complete cell.

A non-ranged form shows the same issue:

arr = [10 20 30]
x = [arr[9] - arr[0]]
x

Expected: [0], not [-10].

Current lowering issue

compileArrayRangeBasic deliberately avoids recording the bounds predicate while compiling an array-literal cell:

if ctx != nil && len(ctx.boundsStack) > 0 && !c.inArrayLiteralCellMode() {
	c.recordStmtBoundsCheck(inBounds)
}

As a result, checkedArrayGet supplies a zero value to expression evaluation, but the collector cell's zero-seeded slot never sees the failed validity condition. The enclosing subtraction therefore computes 0 - 6 on the final iteration.

Simply removing the inArrayLiteralCellMode exclusion fixes scalar cells, but regresses existing multidimensional cases such as out-of-bounds row selection: the generic cell seed does not retain enough runtime shape information to construct the required zero row. Special-casing resultType.Kind() == ArrayKind preserves those tests, but moves semantic resolution policy into the low-level access path and does not provide a general solution for compound array-valued cells.

Desired direction

Carry the checked access's yielded/in-bounds state through the expression and resolve it at the nearest collector-cell boundary. The resolver should:

  • zero-fill the complete scalar cell when any unresolved operand is out of bounds;
  • construct a correctly shaped zero for array-valued cells;
  • preserve closer resolvers such as a future checked-access || fallback;
  • keep temporary ownership and cleanup correct on failed paths.

This matches the outcome/validity model documented in docs/Pluto Conditional Value Semantics.md: no fabricated zero should flow through arithmetic; zero should be introduced only by the collector resolver.

Acceptance criteria

  • The ranged reproduction outputs Diff: [-2 3 -3 4 4 -7 4 0].
  • [arr[9] - arr[0]] outputs [0].
  • Existing scalar and multidimensional collector OOB behavior remains unchanged, including shaped zero rows.
  • Regression coverage includes fixed and ranged compound cells.
  • The full leak-enabled suite passes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions