From 728422fe91b9c102c03da55107072a0721a577ea Mon Sep 17 00:00:00 2001 From: Connor Tsui Date: Fri, 10 Jul 2026 14:21:37 +0100 Subject: [PATCH] Document Union nullability contract Signed-off-by: Connor Tsui --- vortex-array/src/dtype/dtype_impl.rs | 8 +++++++- vortex-array/src/dtype/mod.rs | 10 ++++++++++ vortex-array/src/dtype/union.rs | 3 +++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/vortex-array/src/dtype/dtype_impl.rs b/vortex-array/src/dtype/dtype_impl.rs index e13262fc168..1fe2b953ce3 100644 --- a/vortex-array/src/dtype/dtype_impl.rs +++ b/vortex-array/src/dtype/dtype_impl.rs @@ -80,7 +80,13 @@ impl DType { self.with_nullability(Nullability::Nullable) } - /// Get a new DType with the given nullability (but otherwise the same as `self`) + /// Get a new `DType` with the given nullability (but otherwise the same as `self`). + /// + /// For [`DType::Union`], this currently changes only the union-level nullability summary. It + /// does not rewrite the variants and can therefore produce a `DType` that fails + /// [`UnionVariants::nullability_constraints_satisfied`](crate::dtype::UnionVariants::nullability_constraints_satisfied). + /// Until [union nullability-changing operations](https://github.com/vortex-data/vortex/issues/7882) + /// are defined, construct union variants and their matching nullability explicitly instead. pub fn with_nullability(&self, nullability: Nullability) -> Self { match self { Null => Null, diff --git a/vortex-array/src/dtype/mod.rs b/vortex-array/src/dtype/mod.rs index 403531779aa..fc5dacfac69 100644 --- a/vortex-array/src/dtype/mod.rs +++ b/vortex-array/src/dtype/mod.rs @@ -114,6 +114,16 @@ pub enum DType { /// A `Union` is composed of one or more **variants**, each with a name and a `DType`. A per-row /// `i8` tag selects which variant is "live" at that row. /// + /// Union nullability is derived from its variants: a nullable union must have at least one + /// nullable or [`DType::Null`] variant, while a non-nullable union must have neither. A concrete + /// union array has no separate parent validity bitmap. A row is logically null exactly when + /// its selected child value is null; nulls in inactive sparse-child positions are ignored. + /// + /// Operations that change a union's nullability require further design. Until + /// [issue #7882](https://github.com/vortex-data/vortex/issues/7882) is resolved, they should be + /// unsupported unless the output variants and union-level nullability already satisfy the + /// constraint above. + /// /// See [`UnionVariants`] for the type-tag conventions and accessors. Union(UnionVariants, Nullability), diff --git a/vortex-array/src/dtype/union.rs b/vortex-array/src/dtype/union.rs index cb443e87d36..141d394fc0d 100644 --- a/vortex-array/src/dtype/union.rs +++ b/vortex-array/src/dtype/union.rs @@ -345,6 +345,9 @@ impl UnionVariants { /// - `Nullable`: at least one variant is `DType::Null` or has nullable nullability. /// - `NonNullable`: no `DType::Null` variants and no nullable variants. /// + /// This is a type-level summary of whether a selected variant can be null. A concrete union + /// array has no parent validity bitmap; its row validity is the validity of the selected child. + /// /// The check materializes each [`FieldDType`] (so it may be expensive if some are still /// flatbuffer-backed views). ///