Skip to content

Seven cast rules push nullability casts without trivially_cast_nullability #10750

Closed as not planned

Description

@connortsui20

Problem or motivation

The cast-rule contract on Validity::cast_nullability (vortex-array/src/validity.rs) asks a CastReduce rule to call Validity::trivially_cast_nullability, to return Ok(None) when that call cannot prove a nullability cast safe, and to pair the rule with a CastKernel for execution. These cast rules instead push a nullability cast into the child that holds their validity, with no guard:

Encoding Rule Child
RunEnd encodings/runend/src/compute/cast.rs values
ZigZag encodings/zigzag/src/compute/cast.rs encoded
FoR encodings/fastlanes/src/for_/compute/cast.rs encoded
RLE encodings/fastlanes/src/rle/compute/cast.rs indices
ALP encodings/alp/src/alp/compute/cast.rs encoded
ALP-RD encodings/alp/src/alp_rd/compute/cast.rs left parts
DateTimeParts encodings/datetime-parts/src/compute/cast.rs days

From reading the code, no wrong result is visible today, because the null check still runs when the child cast executes. The rules depend on every child cast keeping that check, though. DecimalByteParts had the same gap, and #10746 fixes it with the guard plus a CastKernel.

Proposed solution

Apply the DecimalByteParts fix to each rule: guard it with trivially_cast_nullability, add a CastKernel for the case that needs execution, and test nullable to non-nullable casts with nulls, without nulls and with only nulls. A shared helper for "push a nullability cast into the validity child" can avoid seven copies of the guard.

Open question: does the contract apply to rules that do not inspect validity themselves? The contract asks for a kernel only from rules that do.

Additional context

Found while planning #10701. Research notes: #10633.

Activity

  1. connortsui20 commented on Oct 26, 2026

    @connortsui20
    MemberAuthor

    Closing as not planned. None of these rules returns a wrong result: each one pushes the nullability cast into the child that holds its validity, and the cast of that child fails when a row is null. The same pattern also shows up in Chunked, Sparse and Extension, so a guard plus a CastKernel per encoding would add a lot of code and delay each rewrite until execution without changing any result.

    That answers the open question above: the guard and the kernel are for rules that build a new Validity. #10798 documents both forms on CastReduce, with Dict as the exception. Every push-down encoding already runs test_cast_conformance on a partially valid array, which asserts the error. #10746 has the discussion for DecimalByteParts.


    Generated by Claude Code

  2. added a commit that references this issue on Oct 26, 2026
    bbb562a
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

    featureA feature request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions