Skip to content

fix(builtins): numbers.range_step descending ranges and undefined on bad step - #801

Open
Anand Krishnamoorthi (anakrish) wants to merge 2 commits into
microsoft:mainfrom
anakrish:fix/numbers-range-step
Open

fix(builtins): numbers.range_step descending ranges and undefined on bad step#801
Anand Krishnamoorthi (anakrish) wants to merge 2 commits into
microsoft:mainfrom
anakrish:fix/numbers-range-step

Conversation

@anakrish

Copy link
Copy Markdown
Collaborator

Two semantic fixes for numbers.range_step:

1. Non-positive or non-integer step in non-strict mode

Previously the function returned an error for a non-positive/non-integer step even when strict = false. OPA returns undefined in that case. The fix checks the step validity first and returns Value::Undefined when not strict.

2. Descending ranges and large-integer support

The previous implementation pre-computed num_elements via i64 arithmetic and called bail! when as_i64() returned None (i.e., for bignum integers). This made descending ranges with large integers unusable.

Replace with a direction-aware step: negate the caller-supplied positive step when v1 > v2 so the loop walks downward naturally. This removes the overflow-prone element-count pre-computation entirely, and Vec::new() + enforce_limit() bounds growth as before.

Tests

New tests/interpreter/cases/builtins/numbers/range_step.yaml covering: ascending, step-2, descending, single-element, non-integer-step-undefined (non-strict), zero-step-undefined (non-strict).

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Two semantic fixes for numbers.range_step:

1. Non-positive or non-integer step: previously returned an error even
   in non-strict mode; now returns undefined in non-strict mode (matches
   OPA behaviour) and only errors in strict mode.

2. Descending ranges: the previous implementation attempted to compute
   num_elements via i64 arithmetic and bail if it overflowed. This
   failed for large integers because as_i64() returns None for bignums.
   Replace with a direction-aware step: negate the caller-supplied
   positive step when v1 > v2 so the loop walks downward naturally,
   removing the overflow-prone element-count pre-computation.

- Rework the step guard to check non-integer/non-positive first and
  short-circuit with undefined when not strict
- Compute step = incr or -incr based on v1 <= v2 comparison
- Use Vec::new() instead of with_capacity (element count no longer
  pre-computed, still bounded by enforce_limit)
- Add YAML regression test: ascending, step-2, descending, single-
  element, non-integer-step-undefined, zero-step-undefined

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
OPA v1.19.1 automatically negates the step when start > stop to produce a
descending range. Our implementation matches this. Update builtins.md to
document it rather than leaving the description blank.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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