From afada2e3955143f27747c83b223160e38a9b284c Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 10 Mar 2026 14:16:12 +0000 Subject: [PATCH 1/6] chore[ci]: enable cuda build+lint Signed-off-by: Joe Isaacs --- .github/workflows/ci.yml | 74 ++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98ad552ae4d..1d132b36119 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -482,50 +482,36 @@ jobs: --target x86_64-unknown-linux-gnu \ -p vortex-buffer -p vortex-ffi -p vortex-fastlanes -p vortex-fsst -p vortex-alp -p vortex-array - # cuda-build: - # if: github.repository == 'vortex-data/vortex' - # name: "CUDA build" - # timeout-minutes: 120 - # runs-on: runs-on=${{ github.run_id }}/runner=gpu/tag=cuda-build - # steps: - # - uses: runs-on/action@v2 - # with: - # sccache: s3 - # - uses: actions/checkout@v6 - # - uses: ./.github/actions/setup-rust - # with: - # repo-token: ${{ secrets.GITHUB_TOKEN }} - # - name: Build CUDA crates - # run: | - # cargo build --locked --all-features --all-targets \ - # -p vortex-cuda \ - # -p vortex-cub \ - # -p vortex-nvcomp \ - # -p gpu-scan-cli \ - # -p vortex-test-e2e-cuda - - # cuda-lint: - # if: github.repository == 'vortex-data/vortex' - # name: "CUDA (lint)" - # timeout-minutes: 120 - # runs-on: runs-on=${{ github.run_id }}/runner=gpu/tag=cuda-lint - # steps: - # - uses: runs-on/action@v2 - # with: - # sccache: s3 - # - uses: actions/checkout@v6 - # - uses: ./.github/actions/setup-rust - # with: - # repo-token: ${{ secrets.GITHUB_TOKEN }} - # - name: Clippy CUDA crates - # run: | - # cargo clippy --locked --all-features --all-targets \ - # -p vortex-cuda \ - # -p vortex-cub \ - # -p vortex-nvcomp \ - # -p gpu-scan-cli \ - # -p vortex-test-e2e-cuda \ - # -- -D warnings + cuda-build-lint: + if: github.repository == 'vortex-data/vortex' + name: "CUDA build & lint" + timeout-minutes: 120 + runs-on: runs-on=${{ github.run_id }}/runner=gpu/tag=cuda-build + steps: + - uses: runs-on/action@v2 + with: + sccache: s3 + - uses: actions/checkout@v6 + - uses: ./.github/actions/setup-rust + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Build CUDA crates + run: | + cargo build --locked --all-features --all-targets \ + -p vortex-cuda \ + -p vortex-cub \ + -p vortex-nvcomp \ + -p gpu-scan-cli \ + -p vortex-test-e2e-cuda + - name: Clippy CUDA crates + run: | + cargo clippy --locked --all-features --all-targets \ + -p vortex-cuda \ + -p vortex-cub \ + -p vortex-nvcomp \ + -p gpu-scan-cli \ + -p vortex-test-e2e-cuda \ + -- -D warnings cuda-test: if: github.repository == 'vortex-data/vortex' From c0c84e8ce26623c4905819c55b9977a3a1076ca6 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 10 Mar 2026 17:07:29 +0000 Subject: [PATCH 2/6] wip Signed-off-by: Joe Isaacs --- encodings/alp/src/alp/array.rs | 9 +- encodings/alp/src/alp_rd/array.rs | 6 +- encodings/bytebool/src/array.rs | 6 +- encodings/datetime-parts/src/array.rs | 8 +- .../src/decimal_byte_parts/mod.rs | 6 +- .../fastlanes/src/bitpacking/vtable/mod.rs | 8 +- encodings/fastlanes/src/delta/vtable/mod.rs | 8 +- encodings/fastlanes/src/for/vtable/mod.rs | 6 +- encodings/fastlanes/src/rle/vtable/mod.rs | 8 +- encodings/fsst/src/array.rs | 6 +- encodings/pco/src/array.rs | 6 +- encodings/runend/src/array.rs | 6 +- encodings/sequence/src/array.rs | 6 +- encodings/sparse/src/lib.rs | 6 +- encodings/zigzag/src/array.rs | 6 +- encodings/zstd/src/array.rs | 6 +- encodings/zstd/src/zstd_buffers.rs | 6 +- vortex-array/src/array/mod.rs | 5 + vortex-array/src/arrays/bool/vtable/mod.rs | 7 +- vortex-array/src/arrays/chunked/vtable/mod.rs | 8 +- .../src/arrays/constant/vtable/mod.rs | 8 +- vortex-array/src/arrays/decimal/vtable/mod.rs | 7 +- vortex-array/src/arrays/dict/vtable/mod.rs | 10 +- .../src/arrays/extension/vtable/mod.rs | 7 +- vortex-array/src/arrays/filter/vtable.rs | 10 +- .../src/arrays/fixed_size_list/vtable/mod.rs | 7 +- vortex-array/src/arrays/list/vtable/mod.rs | 8 +- .../src/arrays/listview/vtable/mod.rs | 7 +- vortex-array/src/arrays/masked/vtable/mod.rs | 8 +- vortex-array/src/arrays/null/mod.rs | 7 +- .../src/arrays/primitive/vtable/mod.rs | 7 +- .../src/arrays/scalar_fn/vtable/mod.rs | 9 +- vortex-array/src/arrays/shared/vtable.rs | 6 +- vortex-array/src/arrays/slice/vtable.rs | 8 +- vortex-array/src/arrays/struct_/vtable/mod.rs | 7 +- vortex-array/src/arrays/varbin/vtable/mod.rs | 8 +- .../src/arrays/varbinview/vtable/mod.rs | 7 +- vortex-array/src/executor.rs | 122 +++++++++++++----- vortex-array/src/vtable/dyn_.rs | 43 ++++-- vortex-array/src/vtable/mod.rs | 12 +- vortex-python/src/arrays/py/vtable.rs | 4 +- 41 files changed, 263 insertions(+), 182 deletions(-) diff --git a/encodings/alp/src/alp/array.rs b/encodings/alp/src/alp/array.rs index 99e166bac18..0bc1c2ee3d4 100644 --- a/encodings/alp/src/alp/array.rs +++ b/encodings/alp/src/alp/array.rs @@ -10,7 +10,7 @@ use vortex_array::ArrayRef; use vortex_array::DeserializeMetadata; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -235,10 +235,9 @@ impl VTable for ALPVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - // TODO(joe): take by value - Ok(ExecutionStep::Done( - execute_decompress(array.clone(), ctx)?.into_array(), + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + execute_decompress(array, ctx)?.into_array(), )) } diff --git a/encodings/alp/src/alp_rd/array.rs b/encodings/alp/src/alp_rd/array.rs index d98b596eaa8..ec9a3fd1eab 100644 --- a/encodings/alp/src/alp_rd/array.rs +++ b/encodings/alp/src/alp_rd/array.rs @@ -11,7 +11,7 @@ use vortex_array::ArrayRef; use vortex_array::DeserializeMetadata; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -296,7 +296,7 @@ impl VTable for ALPRDVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { let left_parts = array.left_parts().clone().execute::(ctx)?; let right_parts = array.right_parts().clone().execute::(ctx)?; @@ -335,7 +335,7 @@ impl VTable for ALPRDVTable { ) }; - Ok(ExecutionStep::Done(decoded_array.into_array())) + Ok(ExecutionResult::done(decoded_array.into_array())) } fn reduce_parent( diff --git a/encodings/bytebool/src/array.rs b/encodings/bytebool/src/array.rs index 8c5c7c9fa31..5b48eccea14 100644 --- a/encodings/bytebool/src/array.rs +++ b/encodings/bytebool/src/array.rs @@ -9,7 +9,7 @@ use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::EmptyMetadata; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::arrays::BoolArray; @@ -183,10 +183,10 @@ impl VTable for ByteBoolVTable { crate::rules::RULES.evaluate(array, parent, child_idx) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { let boolean_buffer = BitBuffer::from(array.as_slice()); let validity = array.validity().clone(); - Ok(ExecutionStep::Done( + Ok(ExecutionResult::done( BoolArray::new(boolean_buffer, validity).into_array(), )) } diff --git a/encodings/datetime-parts/src/array.rs b/encodings/datetime-parts/src/array.rs index e1f51d5ab66..72f1ee422ad 100644 --- a/encodings/datetime-parts/src/array.rs +++ b/encodings/datetime-parts/src/array.rs @@ -10,7 +10,7 @@ use vortex_array::ArrayRef; use vortex_array::DeserializeMetadata; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -222,9 +222,9 @@ impl VTable for DateTimePartsVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done( - decode_to_temporal(array, ctx)?.into_array(), + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + decode_to_temporal(&array, ctx)?.into_array(), )) } diff --git a/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs b/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs index 79e24e1b0cd..b926dad453e 100644 --- a/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs +++ b/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs @@ -13,7 +13,7 @@ use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -190,8 +190,8 @@ impl VTable for DecimalBytePartsVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - to_canonical_decimal(array, ctx).map(ExecutionStep::Done) + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + to_canonical_decimal(&array, ctx).map(ExecutionResult::done) } fn execute_parent( diff --git a/encodings/fastlanes/src/bitpacking/vtable/mod.rs b/encodings/fastlanes/src/bitpacking/vtable/mod.rs index facb2aa5a4f..f034c159e43 100644 --- a/encodings/fastlanes/src/bitpacking/vtable/mod.rs +++ b/encodings/fastlanes/src/bitpacking/vtable/mod.rs @@ -8,7 +8,7 @@ use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::DeserializeMetadata; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -354,8 +354,10 @@ impl VTable for BitPackedVTable { }) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(unpack_array(array, ctx)?.into_array())) + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + unpack_array(&array, ctx)?.into_array(), + )) } fn execute_parent( diff --git a/encodings/fastlanes/src/delta/vtable/mod.rs b/encodings/fastlanes/src/delta/vtable/mod.rs index 5bf67a561c5..dc298b736f0 100644 --- a/encodings/fastlanes/src/delta/vtable/mod.rs +++ b/encodings/fastlanes/src/delta/vtable/mod.rs @@ -9,7 +9,7 @@ use vortex_array::ArrayEq; use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -190,9 +190,9 @@ impl VTable for DeltaVTable { DeltaArray::try_new(bases, deltas, metadata.0.offset as usize, len) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done( - delta_decompress(array, ctx)?.into_array(), + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + delta_decompress(&array, ctx)?.into_array(), )) } } diff --git a/encodings/fastlanes/src/for/vtable/mod.rs b/encodings/fastlanes/src/for/vtable/mod.rs index 1560c721e21..c797ae3187c 100644 --- a/encodings/fastlanes/src/for/vtable/mod.rs +++ b/encodings/fastlanes/src/for/vtable/mod.rs @@ -8,7 +8,7 @@ use vortex_array::ArrayEq; use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::buffer::BufferHandle; @@ -166,8 +166,8 @@ impl VTable for FoRVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(decompress(array, ctx)?.into_array())) + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(decompress(&array, ctx)?.into_array())) } fn execute_parent( diff --git a/encodings/fastlanes/src/rle/vtable/mod.rs b/encodings/fastlanes/src/rle/vtable/mod.rs index ab12a22294d..2c5f904df95 100644 --- a/encodings/fastlanes/src/rle/vtable/mod.rs +++ b/encodings/fastlanes/src/rle/vtable/mod.rs @@ -8,7 +8,7 @@ use vortex_array::ArrayEq; use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -231,9 +231,9 @@ impl VTable for RLEVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done( - rle_decompress(array, ctx)?.into_array(), + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + rle_decompress(&array, ctx)?.into_array(), )) } } diff --git a/encodings/fsst/src/array.rs b/encodings/fsst/src/array.rs index 2f10b0b1a47..3e27e5bc64e 100644 --- a/encodings/fsst/src/array.rs +++ b/encodings/fsst/src/array.rs @@ -17,7 +17,7 @@ use vortex_array::Canonical; use vortex_array::DeserializeMetadata; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -339,8 +339,8 @@ impl VTable for FSSTVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - canonicalize_fsst(array, ctx).map(ExecutionStep::Done) + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + canonicalize_fsst(&array, ctx).map(ExecutionResult::done) } fn execute_parent( diff --git a/encodings/pco/src/array.rs b/encodings/pco/src/array.rs index 4b87e49eb70..6aec7000f18 100644 --- a/encodings/pco/src/array.rs +++ b/encodings/pco/src/array.rs @@ -20,7 +20,7 @@ use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -263,8 +263,8 @@ impl VTable for PcoVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.decompress()?.into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array.decompress()?.into_array())) } fn reduce_parent( diff --git a/encodings/runend/src/array.rs b/encodings/runend/src/array.rs index f943b747cda..a5330c733f9 100644 --- a/encodings/runend/src/array.rs +++ b/encodings/runend/src/array.rs @@ -10,7 +10,7 @@ use vortex_array::ArrayRef; use vortex_array::DeserializeMetadata; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -203,8 +203,8 @@ impl VTable for RunEndVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - run_end_canonicalize(array, ctx).map(ExecutionStep::Done) + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + run_end_canonicalize(&array, ctx).map(ExecutionResult::done) } } diff --git a/encodings/sequence/src/array.rs b/encodings/sequence/src/array.rs index d7149bb3dab..3a697397d40 100644 --- a/encodings/sequence/src/array.rs +++ b/encodings/sequence/src/array.rs @@ -7,7 +7,7 @@ use num_traits::cast::FromPrimitive; use vortex_array::ArrayRef; use vortex_array::DeserializeMetadata; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::Precision; use vortex_array::ProstMetadata; use vortex_array::SerializeMetadata; @@ -381,8 +381,8 @@ impl VTable for SequenceVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - sequence_decompress(array).map(ExecutionStep::Done) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + sequence_decompress(&array).map(ExecutionResult::done) } fn execute_parent( diff --git a/encodings/sparse/src/lib.rs b/encodings/sparse/src/lib.rs index b2bf1e81ae9..7276a725bb8 100644 --- a/encodings/sparse/src/lib.rs +++ b/encodings/sparse/src/lib.rs @@ -11,7 +11,7 @@ use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ToCanonical; @@ -256,8 +256,8 @@ impl VTable for SparseVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - execute_sparse(array, ctx).map(ExecutionStep::Done) + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + execute_sparse(&array, ctx).map(ExecutionResult::done) } } diff --git a/encodings/zigzag/src/array.rs b/encodings/zigzag/src/array.rs index f8139246880..3563055f3b8 100644 --- a/encodings/zigzag/src/array.rs +++ b/encodings/zigzag/src/array.rs @@ -9,7 +9,7 @@ use vortex_array::ArrayRef; use vortex_array::DynArray; use vortex_array::EmptyMetadata; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::buffer::BufferHandle; @@ -149,8 +149,8 @@ impl VTable for ZigZagVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done( + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( zigzag_decode(array.encoded().clone().execute(ctx)?).into_array(), )) } diff --git a/encodings/zstd/src/array.rs b/encodings/zstd/src/array.rs index 52665408abb..59a3cb96806 100644 --- a/encodings/zstd/src/array.rs +++ b/encodings/zstd/src/array.rs @@ -13,7 +13,7 @@ use vortex_array::ArrayRef; use vortex_array::Canonical; use vortex_array::DynArray; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::IntoArray; use vortex_array::Precision; use vortex_array::ProstMetadata; @@ -272,11 +272,11 @@ impl VTable for ZstdVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { array .decompress()? .execute::(ctx) - .map(ExecutionStep::Done) + .map(ExecutionResult::done) } fn reduce_parent( diff --git a/encodings/zstd/src/zstd_buffers.rs b/encodings/zstd/src/zstd_buffers.rs index ff733475a95..d7da9efb8b3 100644 --- a/encodings/zstd/src/zstd_buffers.rs +++ b/encodings/zstd/src/zstd_buffers.rs @@ -10,7 +10,7 @@ use vortex_array::ArrayEq; use vortex_array::ArrayHash; use vortex_array::ArrayRef; use vortex_array::ExecutionCtx; -use vortex_array::ExecutionStep; +use vortex_array::ExecutionResult; use vortex_array::Precision; use vortex_array::ProstMetadata; use vortex_array::buffer::BufferHandle; @@ -467,12 +467,12 @@ impl VTable for ZstdBuffersVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { let session = ctx.session(); let inner_array = array.decompress_and_build_inner(session)?; inner_array .execute::(ctx) - .map(ExecutionStep::Done) + .map(ExecutionResult::done) } } diff --git a/vortex-array/src/array/mod.rs b/vortex-array/src/array/mod.rs index fa141141e33..80f5114f3a6 100644 --- a/vortex-array/src/array/mod.rs +++ b/vortex-array/src/array/mod.rs @@ -402,6 +402,11 @@ impl ArrayAdapter { pub fn as_inner(&self) -> &V::Array { &self.0 } + + /// Consume the adapter and return the underlying array. + pub fn into_inner(self) -> V::Array { + self.0 + } } impl Debug for ArrayAdapter { diff --git a/vortex-array/src/arrays/bool/vtable/mod.rs b/vortex-array/src/arrays/bool/vtable/mod.rs index 9063bd384bc..35f8a924206 100644 --- a/vortex-array/src/arrays/bool/vtable/mod.rs +++ b/vortex-array/src/arrays/bool/vtable/mod.rs @@ -12,8 +12,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::DeserializeMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::ProstMetadata; use crate::SerializeMetadata; use crate::arrays::BoolArray; @@ -185,8 +184,8 @@ impl VTable for BoolVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } fn reduce_parent( diff --git a/vortex-array/src/arrays/chunked/vtable/mod.rs b/vortex-array/src/arrays/chunked/vtable/mod.rs index d5b6b6259da..0cf3a9253ee 100644 --- a/vortex-array/src/arrays/chunked/vtable/mod.rs +++ b/vortex-array/src/arrays/chunked/vtable/mod.rs @@ -15,7 +15,7 @@ use crate::ArrayRef; use crate::Canonical; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; +use crate::ExecutionResult; use crate::IntoArray; use crate::Precision; use crate::ToCanonical; @@ -240,8 +240,10 @@ impl VTable for ChunkedVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(_canonicalize(array, ctx)?.into_array())) + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + _canonicalize(&array, ctx)?.into_array(), + )) } fn reduce(array: &Self::Array) -> VortexResult> { diff --git a/vortex-array/src/arrays/constant/vtable/mod.rs b/vortex-array/src/arrays/constant/vtable/mod.rs index 12fee7869d2..0c774c3f20b 100644 --- a/vortex-array/src/arrays/constant/vtable/mod.rs +++ b/vortex-array/src/arrays/constant/vtable/mod.rs @@ -13,7 +13,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::ExecutionCtx; -use crate::ExecutionStep; +use crate::ExecutionResult; use crate::IntoArray; use crate::Precision; use crate::arrays::ConstantArray; @@ -178,9 +178,9 @@ impl VTable for ConstantVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done( - constant_canonicalize(array)?.into_array(), + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + constant_canonicalize(&array)?.into_array(), )) } diff --git a/vortex-array/src/arrays/decimal/vtable/mod.rs b/vortex-array/src/arrays/decimal/vtable/mod.rs index 7eb78acb832..0039a18e7f5 100644 --- a/vortex-array/src/arrays/decimal/vtable/mod.rs +++ b/vortex-array/src/arrays/decimal/vtable/mod.rs @@ -13,8 +13,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::DeserializeMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::ProstMetadata; use crate::SerializeMetadata; use crate::arrays::DecimalArray; @@ -207,8 +206,8 @@ impl VTable for DecimalVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } fn reduce_parent( diff --git a/vortex-array/src/arrays/dict/vtable/mod.rs b/vortex-array/src/arrays/dict/vtable/mod.rs index ffde0e4223b..c0ca0d38dd8 100644 --- a/vortex-array/src/arrays/dict/vtable/mod.rs +++ b/vortex-array/src/arrays/dict/vtable/mod.rs @@ -29,7 +29,7 @@ use crate::dtype::DType; use crate::dtype::Nullability; use crate::dtype::PType; use crate::executor::ExecutionCtx; -use crate::executor::ExecutionStep; +use crate::executor::ExecutionResult; use crate::hash::ArrayEq; use crate::hash::ArrayHash; use crate::scalar::Scalar; @@ -191,9 +191,9 @@ impl VTable for DictVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - if let Some(canonical) = execute_fast_path(array, ctx)? { - return Ok(ExecutionStep::Done(canonical)); + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + if let Some(canonical) = execute_fast_path(&array, ctx)? { + return Ok(ExecutionResult::done(canonical)); } // TODO(joe): if the values are constant return a constant @@ -209,7 +209,7 @@ impl VTable for DictVTable { // TODO(ngates): if indices min is quite high, we could slice self and offset the indices // such that canonicalize does less work. - Ok(ExecutionStep::Done( + Ok(ExecutionResult::done( take_canonical(values, &codes, ctx)?.into_array(), )) } diff --git a/vortex-array/src/arrays/extension/vtable/mod.rs b/vortex-array/src/arrays/extension/vtable/mod.rs index e99db442573..e2b96cb64de 100644 --- a/vortex-array/src/arrays/extension/vtable/mod.rs +++ b/vortex-array/src/arrays/extension/vtable/mod.rs @@ -18,8 +18,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::Precision; use crate::arrays::ExtensionArray; use crate::arrays::extension::compute::rules::PARENT_RULES; @@ -150,8 +149,8 @@ impl VTable for ExtensionVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } fn reduce_parent( diff --git a/vortex-array/src/arrays/filter/vtable.rs b/vortex-array/src/arrays/filter/vtable.rs index 28d31c60d2b..11e475308e8 100644 --- a/vortex-array/src/arrays/filter/vtable.rs +++ b/vortex-array/src/arrays/filter/vtable.rs @@ -27,7 +27,7 @@ use crate::arrays::filter::rules::RULES; use crate::buffer::BufferHandle; use crate::dtype::DType; use crate::executor::ExecutionCtx; -use crate::executor::ExecutionStep; +use crate::executor::ExecutionResult; use crate::scalar::Scalar; use crate::serde::ArrayChildren; use crate::stats::StatsSetRef; @@ -155,9 +155,9 @@ impl VTable for FilterVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - if let Some(canonical) = execute_filter_fast_paths(array, ctx)? { - return Ok(ExecutionStep::Done(canonical)); + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + if let Some(canonical) = execute_filter_fast_paths(&array, ctx)? { + return Ok(ExecutionResult::done(canonical)); } let Mask::Values(mask_values) = &array.mask else { unreachable!("`execute_filter_fast_paths` handles AllTrue and AllFalse") @@ -165,7 +165,7 @@ impl VTable for FilterVTable { // We rely on the optimization pass that runs prior to this execution for filter pushdown, // so now we can just execute the filter without worrying. - Ok(ExecutionStep::Done( + Ok(ExecutionResult::done( execute_filter(array.child.clone().execute(ctx)?, mask_values).into_array(), )) } diff --git a/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs b/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs index 6922bd12e7f..a7a4758598e 100644 --- a/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs +++ b/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs @@ -13,8 +13,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::Precision; use crate::arrays::FixedSizeListArray; use crate::arrays::fixed_size_list::compute::rules::PARENT_RULES; @@ -219,7 +218,7 @@ impl VTable for FixedSizeListVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } } diff --git a/vortex-array/src/arrays/list/vtable/mod.rs b/vortex-array/src/arrays/list/vtable/mod.rs index 13c5afcd2e0..7765040af8f 100644 --- a/vortex-array/src/arrays/list/vtable/mod.rs +++ b/vortex-array/src/arrays/list/vtable/mod.rs @@ -13,7 +13,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::DynArray; use crate::ExecutionCtx; -use crate::ExecutionStep; +use crate::ExecutionResult; use crate::IntoArray; use crate::Precision; use crate::ProstMetadata; @@ -211,9 +211,9 @@ impl VTable for ListVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done( - list_view_from_list(array.clone(), ctx)?.into_array(), + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + list_view_from_list(array, ctx)?.into_array(), )) } diff --git a/vortex-array/src/arrays/listview/vtable/mod.rs b/vortex-array/src/arrays/listview/vtable/mod.rs index 45fd1f96cfb..35e4ac994aa 100644 --- a/vortex-array/src/arrays/listview/vtable/mod.rs +++ b/vortex-array/src/arrays/listview/vtable/mod.rs @@ -13,8 +13,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::DeserializeMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::Precision; use crate::ProstMetadata; use crate::SerializeMetadata; @@ -239,8 +238,8 @@ impl VTable for ListViewVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } fn reduce_parent( diff --git a/vortex-array/src/arrays/masked/vtable/mod.rs b/vortex-array/src/arrays/masked/vtable/mod.rs index dafd40a50ee..8172212ca33 100644 --- a/vortex-array/src/arrays/masked/vtable/mod.rs +++ b/vortex-array/src/arrays/masked/vtable/mod.rs @@ -25,7 +25,7 @@ use crate::arrays::masked::mask_validity_canonical; use crate::buffer::BufferHandle; use crate::dtype::DType; use crate::executor::ExecutionCtx; -use crate::executor::ExecutionStep; +use crate::executor::ExecutionResult; use crate::hash::ArrayEq; use crate::hash::ArrayHash; use crate::scalar::Scalar; @@ -161,12 +161,12 @@ impl VTable for MaskedVTable { MaskedArray::try_new(child, validity) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { let validity_mask = array.validity_mask()?; // Fast path: all masked means result is all nulls. if validity_mask.all_false() { - return Ok(ExecutionStep::Done( + return Ok(ExecutionResult::done( ConstantArray::new(Scalar::null(array.dtype().as_nullable()), array.len()) .into_array(), )); @@ -179,7 +179,7 @@ impl VTable for MaskedVTable { // `AllTrue` masks (no data copying), so there's no benefit. let child = array.child().clone().execute::(ctx)?; - Ok(ExecutionStep::Done( + Ok(ExecutionResult::done( mask_validity_canonical(child, &validity_mask, ctx)?.into_array(), )) } diff --git a/vortex-array/src/arrays/null/mod.rs b/vortex-array/src/arrays/null/mod.rs index 5b83164333a..8495c0074bf 100644 --- a/vortex-array/src/arrays/null/mod.rs +++ b/vortex-array/src/arrays/null/mod.rs @@ -11,8 +11,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::Precision; use crate::arrays::null::compute::rules::PARENT_RULES; use crate::buffer::BufferHandle; @@ -132,8 +131,8 @@ impl VTable for NullVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } } diff --git a/vortex-array/src/arrays/primitive/vtable/mod.rs b/vortex-array/src/arrays/primitive/vtable/mod.rs index 3418eb1f822..315df8450d3 100644 --- a/vortex-array/src/arrays/primitive/vtable/mod.rs +++ b/vortex-array/src/arrays/primitive/vtable/mod.rs @@ -11,8 +11,7 @@ use vortex_error::vortex_panic; use crate::ArrayRef; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::arrays::PrimitiveArray; use crate::buffer::BufferHandle; use crate::dtype::DType; @@ -199,8 +198,8 @@ impl VTable for PrimitiveVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } fn reduce_parent( diff --git a/vortex-array/src/arrays/scalar_fn/vtable/mod.rs b/vortex-array/src/arrays/scalar_fn/vtable/mod.rs index c1dca2b3168..e0f6cd0d41f 100644 --- a/vortex-array/src/arrays/scalar_fn/vtable/mod.rs +++ b/vortex-array/src/arrays/scalar_fn/vtable/mod.rs @@ -30,7 +30,7 @@ use crate::arrays::scalar_fn::rules::RULES; use crate::buffer::BufferHandle; use crate::dtype::DType; use crate::executor::ExecutionCtx; -use crate::executor::ExecutionStep; +use crate::executor::ExecutionResult; use crate::expr::Expression; use crate::matcher::Matcher; use crate::scalar_fn; @@ -195,10 +195,13 @@ impl VTable for ScalarFnVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { ctx.log(format_args!("scalar_fn({}): executing", array.scalar_fn)); let args = VecExecutionArgs::new(array.children.clone(), array.len); - array.scalar_fn.execute(&args, ctx).map(ExecutionStep::Done) + array + .scalar_fn + .execute(&args, ctx) + .map(ExecutionResult::done) } fn reduce(array: &Self::Array) -> VortexResult> { diff --git a/vortex-array/src/arrays/shared/vtable.rs b/vortex-array/src/arrays/shared/vtable.rs index 12106400338..d02515c9cc2 100644 --- a/vortex-array/src/arrays/shared/vtable.rs +++ b/vortex-array/src/arrays/shared/vtable.rs @@ -12,7 +12,7 @@ use crate::ArrayRef; use crate::Canonical; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; +use crate::ExecutionResult; use crate::Precision; use crate::arrays::SharedArray; use crate::buffer::BufferHandle; @@ -145,10 +145,10 @@ impl VTable for SharedVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { array .get_or_compute(|source| source.clone().execute::(ctx)) - .map(ExecutionStep::Done) + .map(ExecutionResult::done) } } impl OperationsVTable for SharedVTable { diff --git a/vortex-array/src/arrays/slice/vtable.rs b/vortex-array/src/arrays/slice/vtable.rs index a8aaafb1d61..a5b3acca03c 100644 --- a/vortex-array/src/arrays/slice/vtable.rs +++ b/vortex-array/src/arrays/slice/vtable.rs @@ -26,7 +26,7 @@ use crate::arrays::slice::rules::PARENT_RULES; use crate::buffer::BufferHandle; use crate::dtype::DType; use crate::executor::ExecutionCtx; -use crate::executor::ExecutionStep; +use crate::executor::ExecutionResult; use crate::scalar::Scalar; use crate::serde::ArrayChildren; use crate::stats::StatsSetRef; @@ -155,7 +155,7 @@ impl VTable for SliceVTable { Ok(()) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { // Execute the child to get canonical form, then slice it let Some(canonical) = array.child.as_opt::() else { // If the child is not canonical, recurse. @@ -164,14 +164,14 @@ impl VTable for SliceVTable { .clone() .execute::(ctx)? .slice(array.slice_range().clone()) - .map(ExecutionStep::Done); + .map(ExecutionResult::done); }; // TODO(ngates): we should inline canonical slice logic here. Canonical::from(canonical) .as_ref() .slice(array.range.clone()) - .map(ExecutionStep::Done) + .map(ExecutionResult::done) } fn reduce_parent( diff --git a/vortex-array/src/arrays/struct_/vtable/mod.rs b/vortex-array/src/arrays/struct_/vtable/mod.rs index bbc35b0a67c..9c28907ef12 100644 --- a/vortex-array/src/arrays/struct_/vtable/mod.rs +++ b/vortex-array/src/arrays/struct_/vtable/mod.rs @@ -15,8 +15,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::arrays::StructArray; use crate::arrays::struct_::compute::rules::PARENT_RULES; use crate::buffer::BufferHandle; @@ -207,8 +206,8 @@ impl VTable for StructVTable { Ok(()) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } fn reduce_parent( diff --git a/vortex-array/src/arrays/varbin/vtable/mod.rs b/vortex-array/src/arrays/varbin/vtable/mod.rs index 3f35cd793c4..71421b861ae 100644 --- a/vortex-array/src/arrays/varbin/vtable/mod.rs +++ b/vortex-array/src/arrays/varbin/vtable/mod.rs @@ -10,7 +10,7 @@ use vortex_error::vortex_panic; use crate::ArrayRef; use crate::DeserializeMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; +use crate::ExecutionResult; use crate::IntoArray; use crate::ProstMetadata; use crate::SerializeMetadata; @@ -219,9 +219,9 @@ impl VTable for VarBinVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done( - varbin_to_canonical(array, ctx)?.into_array(), + fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done( + varbin_to_canonical(&array, ctx)?.into_array(), )) } } diff --git a/vortex-array/src/arrays/varbinview/vtable/mod.rs b/vortex-array/src/arrays/varbinview/vtable/mod.rs index 9df6a68636c..2b080be6658 100644 --- a/vortex-array/src/arrays/varbinview/vtable/mod.rs +++ b/vortex-array/src/arrays/varbinview/vtable/mod.rs @@ -17,8 +17,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::EmptyMetadata; use crate::ExecutionCtx; -use crate::ExecutionStep; -use crate::IntoArray; +use crate::ExecutionResult; use crate::Precision; use crate::arrays::VarBinViewArray; use crate::arrays::varbinview::BinaryView; @@ -243,7 +242,7 @@ impl VTable for VarBinViewVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionStep::Done(array.clone().into_array())) + fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + Ok(ExecutionResult::done(array)) } } diff --git a/vortex-array/src/executor.rs b/vortex-array/src/executor.rs index da05450f8de..15306032e55 100644 --- a/vortex-array/src/executor.rs +++ b/vortex-array/src/executor.rs @@ -141,22 +141,24 @@ impl dyn DynArray + '_ { continue; } - // Execute the array itself - match current.vtable().execute(¤t, ctx)? { + // Execute the array itself. + let result = execute_step(current, ctx)?; + let (array, step) = result.into_parts(); + match step { ExecutionStep::ExecuteChild(i, done) => { - let child = current + let child = array .nth_child(i) .vortex_expect("ExecuteChild index in bounds"); ctx.log(format_args!( "ExecuteChild({i}): pushing {}, focusing on {}", - current, child + array, child )); - stack.push((current, i, done)); + stack.push((array, i, done)); current = child.optimize()?; } - ExecutionStep::Done(result) => { - ctx.log(format_args!("Done: {} -> {}", current, result)); - current = result; + ExecutionStep::Done => { + ctx.log(format_args!("Done: {}", array)); + current = array; } } } @@ -305,12 +307,14 @@ impl Executable for ArrayRef { } } - // 4. execute (returns an ExecutionStep) + // 4. execute (returns an ExecutionResult) ctx.log(format_args!("executing {}", array)); - match array.vtable().execute(&array, ctx)? { - ExecutionStep::Done(result) => { - ctx.log(format_args!("-> {}", result.as_ref())); - Ok(result) + let result = execute_step(array, ctx)?; + let (array, step) = result.into_parts(); + match step { + ExecutionStep::Done => { + ctx.log(format_args!("-> {}", array.as_ref())); + Ok(array) } ExecutionStep::ExecuteChild(i, _) => { // For single-step execution, handle ExecuteChild by executing the child, @@ -323,6 +327,21 @@ impl Executable for ArrayRef { } } +/// Execute a single step on an array, consuming it. +/// +/// Extracts the vtable before consuming the array to avoid borrow conflicts. +fn execute_step(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult { + // Extract vtable ref before the move. VTable references are &'static in practice + // (backed by const statics in ArrayVTableAdapter), so we can safely extend the lifetime. + let vtable = array.as_ref().vtable(); + // SAFETY: The vtable is always a &'static reference (see ArrayVTableAdapter::vtable), + // but the DynArray trait signature ties it to &self. We extend the lifetime to allow + // consuming the array. + let vtable: &'static dyn crate::vtable::DynVTable = + unsafe { &*(vtable as *const dyn crate::vtable::DynVTable) }; + vtable.execute(array, ctx) +} + /// Try execute_parent on each child of the array. fn try_execute_parent(array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult> { for child_idx in 0..array.nchildren() { @@ -343,7 +362,7 @@ fn try_execute_parent(array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult< /// A predicate that determines when an array has reached a desired form during execution. pub type DonePredicate = fn(&dyn DynArray) -> bool; -/// The result of a single execution step on an array encoding. +/// Metadata-only step indicator returned alongside an array in [`ExecutionResult`]. /// /// Instead of recursively executing children, encodings return an `ExecutionStep` that tells the /// scheduler what to do next. This enables the scheduler to manage execution iteratively using @@ -355,25 +374,11 @@ pub enum ExecutionStep { /// /// Between steps, the scheduler runs reduce/reduce_parent rules to fixpoint, enabling /// cross-step optimization (e.g., pushing scalar functions through newly-decoded children). - /// - /// Use [`ExecutionStep::execute_child`] instead of constructing this variant directly. ExecuteChild(usize, DonePredicate), - /// Execution is complete. The result may be in any encoding — not necessarily canonical. - /// The scheduler will continue executing the result if it has not yet reached the target form. - Done(ArrayRef), -} - -impl ExecutionStep { - /// Request execution of child at `child_idx` until it matches the given [`Matcher`]. - pub fn execute_child(child_idx: usize) -> Self { - ExecutionStep::ExecuteChild(child_idx, M::matches) - } - - /// Signal that execution is complete with the given result. - pub fn done(result: ArrayRef) -> Self { - ExecutionStep::Done(result) - } + /// Execution is complete. The array in the accompanying [`ExecutionResult`] is the result. + /// The scheduler will continue executing if it has not yet reached the target form. + Done, } impl fmt::Debug for ExecutionStep { @@ -382,9 +387,62 @@ impl fmt::Debug for ExecutionStep { ExecutionStep::ExecuteChild(idx, _) => { f.debug_tuple("ExecuteChild").field(idx).finish() } - ExecutionStep::Done(result) => f.debug_tuple("Done").field(result).finish(), + ExecutionStep::Done => write!(f, "Done"), + } + } +} + +/// The result of a single execution step on an array encoding. +/// +/// Combines an [`ArrayRef`] with an [`ExecutionStep`] to tell the scheduler both what to do next +/// and what array to work with. +pub struct ExecutionResult { + array: ArrayRef, + step: ExecutionStep, +} + +impl ExecutionResult { + /// Signal that execution is complete with the given result array. + pub fn done(result: impl IntoArray) -> Self { + Self { + array: result.into_array(), + step: ExecutionStep::Done, } } + + /// Request execution of child at `child_idx` until it matches the given [`Matcher`]. + /// + /// The provided array is the (possibly modified) parent that still needs its child executed. + pub fn execute_child(array: impl IntoArray, child_idx: usize) -> Self { + Self { + array: array.into_array(), + step: ExecutionStep::ExecuteChild(child_idx, M::matches), + } + } + + /// Returns a reference to the array. + pub fn array(&self) -> &ArrayRef { + &self.array + } + + /// Returns a reference to the step. + pub fn step(&self) -> &ExecutionStep { + &self.step + } + + /// Decompose into parts. + pub fn into_parts(self) -> (ArrayRef, ExecutionStep) { + (self.array, self.step) + } +} + +impl fmt::Debug for ExecutionResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ExecutionResult") + .field("array", &self.array) + .field("step", &self.step) + .finish() + } } /// Extension trait for creating an execution context from a session. diff --git a/vortex-array/src/vtable/dyn_.rs b/vortex-array/src/vtable/dyn_.rs index 64ca5e99c50..90d5859a024 100644 --- a/vortex-array/src/vtable/dyn_.rs +++ b/vortex-array/src/vtable/dyn_.rs @@ -6,6 +6,7 @@ use std::fmt; use std::fmt::Debug; use std::fmt::Formatter; use std::marker::PhantomData; +use std::sync::Arc; use arcref::ArcRef; use vortex_error::VortexExpect; @@ -16,6 +17,7 @@ use vortex_session::VortexSession; use crate::ArrayAdapter; use crate::ArrayRef; use crate::DynArray; +use crate::ExecutionResult; use crate::ExecutionStep; use crate::IntoArray; use crate::buffer::BufferHandle; @@ -61,7 +63,7 @@ pub trait DynVTable: 'static + private::Sealed + Send + Sync + Debug { ) -> VortexResult>; /// See [`VTable::execute`] - fn execute(&self, array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult; + fn execute(&self, array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult; /// See [`VTable::execute_parent`] fn execute_parent( @@ -146,31 +148,34 @@ impl DynVTable for ArrayVTableAdapter { Ok(Some(reduced)) } - fn execute(&self, array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult { - let step = V::execute(downcast::(array), ctx)?; + fn execute(&self, array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult { + // Capture metadata before the move for post-validation and stats inheritance. + let len = array.len(); + let dtype = array.dtype().clone(); + let stats = array.statistics().to_owned(); - if let ExecutionStep::Done(ref result) = step { + let owned = downcast_owned::(array); + let result = V::execute(owned, ctx)?; + + if matches!(result.step(), ExecutionStep::Done) { if cfg!(debug_assertions) { vortex_ensure!( - result.as_ref().len() == array.len(), + result.array().len() == len, "Result length mismatch for {:?}", self ); vortex_ensure!( - result.as_ref().dtype() == array.dtype(), + result.array().dtype() == &dtype, "Executed canonical dtype mismatch for {:?}", self ); } // TODO(ngates): do we want to do this on every execution? We used to in to_canonical. - result - .as_ref() - .statistics() - .inherit_from(array.statistics()); + result.array().statistics().set_iter(stats.into_iter()); } - Ok(step) + Ok(result) } fn execute_parent( @@ -207,6 +212,22 @@ fn downcast(array: &ArrayRef) -> &V::Array { .as_inner() } +/// Downcast an `ArrayRef` into an owned `V::Array`, avoiding a clone when possible. +/// +/// If the `Arc` refcount is 1, the inner array is moved out without cloning. +/// Otherwise, falls back to cloning the inner array. +fn downcast_owned(array: ArrayRef) -> Arc { + let adapter: Arc> = array + .as_any_arc() + .downcast::>() + .ok() + .vortex_expect("Failed to downcast array to expected encoding type"); + match Arc::try_unwrap(adapter) { + Ok(adapter) => adapter.into_inner(), + Err(arc) => unsarc, + } +} + impl Debug for ArrayVTableAdapter { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "Encoding<{}>", type_name::()) diff --git a/vortex-array/src/vtable/mod.rs b/vortex-array/src/vtable/mod.rs index a038a83639a..945106fc361 100644 --- a/vortex-array/src/vtable/mod.rs +++ b/vortex-array/src/vtable/mod.rs @@ -10,6 +10,7 @@ mod validity; use std::fmt::Debug; use std::hash::Hasher; use std::ops::Deref; +use std::sync::Arc; pub use dyn_::*; pub use operations::*; @@ -22,7 +23,7 @@ use vortex_session::VortexSession; use crate::ArrayRef; use crate::Canonical; use crate::DynArray; -use crate::ExecutionStep; +use crate::ExecutionResult; use crate::IntoArray; use crate::Precision; use crate::arrays::ConstantArray; @@ -181,13 +182,12 @@ pub trait VTable: 'static + Sized + Send + Sync + Debug { /// of children must be expected. fn with_children(array: &mut Self::Array, children: Vec) -> VortexResult<()>; - /// Execute this array by returning an [`ExecutionStep`] that tells the scheduler what to + /// Execute this array by returning an [`ExecutionResult`] that tells the scheduler what to /// do next. /// /// Instead of recursively executing children, implementations should return - /// [`ExecutionStep::ExecuteChild(i)`] to request that the scheduler execute a child first, - /// or [`ExecutionStep::Done(result)`] when the - /// encoding can produce a result directly. + /// [`ExecutionResult::execute_child`] to request that the scheduler execute a child first, + /// or [`ExecutionResult::done`] when the encoding can produce a result directly. /// /// Array execution is designed such that repeated execution of an array will eventually /// converge to a canonical representation. Implementations of this function should therefore @@ -198,7 +198,7 @@ pub trait VTable: 'static + Sized + Send + Sync + Debug { /// /// Debug builds will panic if the returned array is of the wrong type, wrong length, or /// incorrectly contains null values. - fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult; + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult; /// Attempt to execute the parent of this array. /// diff --git a/vortex-python/src/arrays/py/vtable.rs b/vortex-python/src/arrays/py/vtable.rs index be3b2ad26a3..9a36c89eba6 100644 --- a/vortex-python/src/arrays/py/vtable.rs +++ b/vortex-python/src/arrays/py/vtable.rs @@ -10,7 +10,7 @@ use pyo3::prelude::*; use pyo3::types::PyBytes; use vortex::array::ArrayRef; use vortex::array::ExecutionCtx; -use vortex::array::ExecutionStep; +use vortex::array::ExecutionResult; use vortex::array::Precision; use vortex::array::RawMetadata; use vortex::array::SerializeMetadata; @@ -156,7 +156,7 @@ impl VTable for PythonVTable { Ok(()) } - fn execute(_array: &Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(_array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { todo!() } } From 7e6bd6137236a09041cddc40195c039b2117d225 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 10 Mar 2026 17:09:07 +0000 Subject: [PATCH 3/6] wip Signed-off-by: Joe Isaacs --- vortex-array/src/vtable/dyn_.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vortex-array/src/vtable/dyn_.rs b/vortex-array/src/vtable/dyn_.rs index 90d5859a024..88938989485 100644 --- a/vortex-array/src/vtable/dyn_.rs +++ b/vortex-array/src/vtable/dyn_.rs @@ -216,7 +216,7 @@ fn downcast(array: &ArrayRef) -> &V::Array { /// /// If the `Arc` refcount is 1, the inner array is moved out without cloning. /// Otherwise, falls back to cloning the inner array. -fn downcast_owned(array: ArrayRef) -> Arc { +fn downcast_owned(array: ArrayRef) -> V::Array { let adapter: Arc> = array .as_any_arc() .downcast::>() @@ -224,7 +224,7 @@ fn downcast_owned(array: ArrayRef) -> Arc { .vortex_expect("Failed to downcast array to expected encoding type"); match Arc::try_unwrap(adapter) { Ok(adapter) => adapter.into_inner(), - Err(arc) => unsarc, + Err(arc) => arc.as_inner().clone(), } } From 25697316bf6cd8092d57fcde087ab9b5ff592517 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 10 Mar 2026 17:25:21 +0000 Subject: [PATCH 4/6] wip Signed-off-by: Joe Isaacs --- encodings/alp/src/alp/array.rs | 4 +++- encodings/alp/src/alp_rd/array.rs | 3 ++- encodings/bytebool/src/array.rs | 3 ++- encodings/datetime-parts/src/array.rs | 3 ++- .../src/decimal_byte_parts/mod.rs | 3 ++- encodings/fastlanes/src/bitpacking/vtable/mod.rs | 3 ++- encodings/fastlanes/src/delta/vtable/mod.rs | 3 ++- encodings/fastlanes/src/for/vtable/mod.rs | 3 ++- encodings/fastlanes/src/rle/vtable/mod.rs | 3 ++- encodings/fsst/src/array.rs | 2 +- encodings/pco/src/array.rs | 3 ++- encodings/runend/src/array.rs | 3 ++- encodings/sequence/src/array.rs | 3 ++- encodings/sparse/src/lib.rs | 3 ++- encodings/zigzag/src/array.rs | 3 ++- encodings/zstd/src/array.rs | 2 +- encodings/zstd/src/zstd_buffers.rs | 2 +- vortex-array/src/arrays/bool/vtable/mod.rs | 3 ++- vortex-array/src/arrays/chunked/vtable/mod.rs | 3 ++- vortex-array/src/arrays/constant/vtable/mod.rs | 3 ++- vortex-array/src/arrays/decimal/vtable/mod.rs | 3 ++- vortex-array/src/arrays/dict/vtable/mod.rs | 3 ++- vortex-array/src/arrays/extension/vtable/mod.rs | 3 ++- vortex-array/src/arrays/filter/vtable.rs | 3 ++- .../src/arrays/fixed_size_list/vtable/mod.rs | 3 ++- vortex-array/src/arrays/list/vtable/mod.rs | 5 +++-- vortex-array/src/arrays/listview/vtable/mod.rs | 3 ++- vortex-array/src/arrays/masked/vtable/mod.rs | 3 ++- vortex-array/src/arrays/null/mod.rs | 3 ++- vortex-array/src/arrays/primitive/vtable/mod.rs | 3 ++- vortex-array/src/arrays/scalar_fn/vtable/mod.rs | 3 ++- vortex-array/src/arrays/shared/vtable.rs | 3 ++- vortex-array/src/arrays/slice/vtable.rs | 3 ++- vortex-array/src/arrays/struct_/vtable/mod.rs | 2 +- vortex-array/src/arrays/varbin/vtable/mod.rs | 3 ++- vortex-array/src/arrays/varbinview/vtable/mod.rs | 2 +- vortex-array/src/vtable/dyn_.rs | 16 ++++++++-------- vortex-array/src/vtable/mod.rs | 9 +++++++++ 38 files changed, 86 insertions(+), 45 deletions(-) diff --git a/encodings/alp/src/alp/array.rs b/encodings/alp/src/alp/array.rs index 0bc1c2ee3d4..4550bd1a613 100644 --- a/encodings/alp/src/alp/array.rs +++ b/encodings/alp/src/alp/array.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use vortex_array::ArrayEq; use vortex_array::ArrayHash; @@ -235,7 +236,8 @@ impl VTable for ALPVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { + let array = Arc::try_unwrap(array).unwrap_or_else(|arc| (*arc).clone()); Ok(ExecutionResult::done( execute_decompress(array, ctx)?.into_array(), )) diff --git a/encodings/alp/src/alp_rd/array.rs b/encodings/alp/src/alp_rd/array.rs index ec9a3fd1eab..cf9c6f22cd6 100644 --- a/encodings/alp/src/alp_rd/array.rs +++ b/encodings/alp/src/alp_rd/array.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use itertools::Itertools; use vortex_array::ArrayEq; @@ -296,7 +297,7 @@ impl VTable for ALPRDVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { let left_parts = array.left_parts().clone().execute::(ctx)?; let right_parts = array.right_parts().clone().execute::(ctx)?; diff --git a/encodings/bytebool/src/array.rs b/encodings/bytebool/src/array.rs index 5b48eccea14..9290ceae5ff 100644 --- a/encodings/bytebool/src/array.rs +++ b/encodings/bytebool/src/array.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use vortex_array::ArrayEq; use vortex_array::ArrayHash; @@ -183,7 +184,7 @@ impl VTable for ByteBoolVTable { crate::rules::RULES.evaluate(array, parent, child_idx) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { let boolean_buffer = BitBuffer::from(array.as_slice()); let validity = array.validity().clone(); Ok(ExecutionResult::done( diff --git a/encodings/datetime-parts/src/array.rs b/encodings/datetime-parts/src/array.rs index 72f1ee422ad..e3b83e02850 100644 --- a/encodings/datetime-parts/src/array.rs +++ b/encodings/datetime-parts/src/array.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use vortex_array::ArrayEq; use vortex_array::ArrayHash; @@ -222,7 +223,7 @@ impl VTable for DateTimePartsVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( decode_to_temporal(&array, ctx)?.into_array(), )) diff --git a/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs b/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs index b926dad453e..cc7f0c25743 100644 --- a/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs +++ b/encodings/decimal-byte-parts/src/decimal_byte_parts/mod.rs @@ -6,6 +6,7 @@ mod rules; mod slice; use std::hash::Hash; +use std::sync::Arc; use prost::Message as _; use vortex_array::ArrayEq; @@ -190,7 +191,7 @@ impl VTable for DecimalBytePartsVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { to_canonical_decimal(&array, ctx).map(ExecutionResult::done) } diff --git a/encodings/fastlanes/src/bitpacking/vtable/mod.rs b/encodings/fastlanes/src/bitpacking/vtable/mod.rs index f034c159e43..a5f45839cff 100644 --- a/encodings/fastlanes/src/bitpacking/vtable/mod.rs +++ b/encodings/fastlanes/src/bitpacking/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use vortex_array::ArrayEq; use vortex_array::ArrayHash; @@ -354,7 +355,7 @@ impl VTable for BitPackedVTable { }) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( unpack_array(&array, ctx)?.into_array(), )) diff --git a/encodings/fastlanes/src/delta/vtable/mod.rs b/encodings/fastlanes/src/delta/vtable/mod.rs index dc298b736f0..917a93cbcb5 100644 --- a/encodings/fastlanes/src/delta/vtable/mod.rs +++ b/encodings/fastlanes/src/delta/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use fastlanes::FastLanes; use prost::Message; @@ -190,7 +191,7 @@ impl VTable for DeltaVTable { DeltaArray::try_new(bases, deltas, metadata.0.offset as usize, len) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( delta_decompress(&array, ctx)?.into_array(), )) diff --git a/encodings/fastlanes/src/for/vtable/mod.rs b/encodings/fastlanes/src/for/vtable/mod.rs index c797ae3187c..251421cb22a 100644 --- a/encodings/fastlanes/src/for/vtable/mod.rs +++ b/encodings/fastlanes/src/for/vtable/mod.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use vortex_array::ArrayEq; use vortex_array::ArrayHash; @@ -166,7 +167,7 @@ impl VTable for FoRVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(decompress(&array, ctx)?.into_array())) } diff --git a/encodings/fastlanes/src/rle/vtable/mod.rs b/encodings/fastlanes/src/rle/vtable/mod.rs index 2c5f904df95..5d20351d495 100644 --- a/encodings/fastlanes/src/rle/vtable/mod.rs +++ b/encodings/fastlanes/src/rle/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use prost::Message; use vortex_array::ArrayEq; @@ -231,7 +232,7 @@ impl VTable for RLEVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( rle_decompress(&array, ctx)?.into_array(), )) diff --git a/encodings/fsst/src/array.rs b/encodings/fsst/src/array.rs index 3e27e5bc64e..6ee6d75d1bb 100644 --- a/encodings/fsst/src/array.rs +++ b/encodings/fsst/src/array.rs @@ -339,7 +339,7 @@ impl VTable for FSSTVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { canonicalize_fsst(&array, ctx).map(ExecutionResult::done) } diff --git a/encodings/pco/src/array.rs b/encodings/pco/src/array.rs index 6aec7000f18..cc418b30a58 100644 --- a/encodings/pco/src/array.rs +++ b/encodings/pco/src/array.rs @@ -4,6 +4,7 @@ use std::cmp; use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use pco::ChunkConfig; use pco::PagingSpec; @@ -263,7 +264,7 @@ impl VTable for PcoVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array.decompress()?.into_array())) } diff --git a/encodings/runend/src/array.rs b/encodings/runend/src/array.rs index a5330c733f9..8ab44108424 100644 --- a/encodings/runend/src/array.rs +++ b/encodings/runend/src/array.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use vortex_array::ArrayEq; use vortex_array::ArrayHash; @@ -203,7 +204,7 @@ impl VTable for RunEndVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { run_end_canonicalize(&array, ctx).map(ExecutionResult::done) } } diff --git a/encodings/sequence/src/array.rs b/encodings/sequence/src/array.rs index 3a697397d40..d493a16ae76 100644 --- a/encodings/sequence/src/array.rs +++ b/encodings/sequence/src/array.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use num_traits::cast::FromPrimitive; use vortex_array::ArrayRef; @@ -381,7 +382,7 @@ impl VTable for SequenceVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { sequence_decompress(&array).map(ExecutionResult::done) } diff --git a/encodings/sparse/src/lib.rs b/encodings/sparse/src/lib.rs index 7276a725bb8..eca81d3cd5c 100644 --- a/encodings/sparse/src/lib.rs +++ b/encodings/sparse/src/lib.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use kernel::PARENT_KERNELS; use prost::Message as _; @@ -256,7 +257,7 @@ impl VTable for SparseVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { execute_sparse(&array, ctx).map(ExecutionResult::done) } } diff --git a/encodings/zigzag/src/array.rs b/encodings/zigzag/src/array.rs index 3563055f3b8..4f6829b9517 100644 --- a/encodings/zigzag/src/array.rs +++ b/encodings/zigzag/src/array.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use vortex_array::ArrayEq; use vortex_array::ArrayHash; @@ -149,7 +150,7 @@ impl VTable for ZigZagVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( zigzag_decode(array.encoded().clone().execute(ctx)?).into_array(), )) diff --git a/encodings/zstd/src/array.rs b/encodings/zstd/src/array.rs index 59a3cb96806..e5509ecb2ea 100644 --- a/encodings/zstd/src/array.rs +++ b/encodings/zstd/src/array.rs @@ -272,7 +272,7 @@ impl VTable for ZstdVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { array .decompress()? .execute::(ctx) diff --git a/encodings/zstd/src/zstd_buffers.rs b/encodings/zstd/src/zstd_buffers.rs index d7da9efb8b3..1673b156352 100644 --- a/encodings/zstd/src/zstd_buffers.rs +++ b/encodings/zstd/src/zstd_buffers.rs @@ -467,7 +467,7 @@ impl VTable for ZstdBuffersVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { let session = ctx.session(); let inner_array = array.decompress_and_build_inner(session)?; inner_array diff --git a/vortex-array/src/arrays/bool/vtable/mod.rs b/vortex-array/src/arrays/bool/vtable/mod.rs index 35f8a924206..95a38a03854 100644 --- a/vortex-array/src/arrays/bool/vtable/mod.rs +++ b/vortex-array/src/arrays/bool/vtable/mod.rs @@ -31,6 +31,7 @@ mod operations; mod validity; use std::hash::Hash; +use std::sync::Arc; use crate::Precision; use crate::arrays::bool::compute::rules::RULES; @@ -184,7 +185,7 @@ impl VTable for BoolVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } diff --git a/vortex-array/src/arrays/chunked/vtable/mod.rs b/vortex-array/src/arrays/chunked/vtable/mod.rs index 0cf3a9253ee..e972d6feb0e 100644 --- a/vortex-array/src/arrays/chunked/vtable/mod.rs +++ b/vortex-array/src/arrays/chunked/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use itertools::Itertools; use vortex_error::VortexResult; @@ -240,7 +241,7 @@ impl VTable for ChunkedVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( _canonicalize(&array, ctx)?.into_array(), )) diff --git a/vortex-array/src/arrays/constant/vtable/mod.rs b/vortex-array/src/arrays/constant/vtable/mod.rs index 0c774c3f20b..f011ed3ff20 100644 --- a/vortex-array/src/arrays/constant/vtable/mod.rs +++ b/vortex-array/src/arrays/constant/vtable/mod.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::hash::Hash; +use std::sync::Arc; use vortex_buffer::ByteBufferMut; use vortex_error::VortexExpect; @@ -178,7 +179,7 @@ impl VTable for ConstantVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( constant_canonicalize(&array)?.into_array(), )) diff --git a/vortex-array/src/arrays/decimal/vtable/mod.rs b/vortex-array/src/arrays/decimal/vtable/mod.rs index 0039a18e7f5..8dcc871d89e 100644 --- a/vortex-array/src/arrays/decimal/vtable/mod.rs +++ b/vortex-array/src/arrays/decimal/vtable/mod.rs @@ -34,6 +34,7 @@ mod operations; mod validity; use std::hash::Hash; +use std::sync::Arc; use crate::Precision; use crate::arrays::decimal::compute::rules::RULES; @@ -206,7 +207,7 @@ impl VTable for DecimalVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } diff --git a/vortex-array/src/arrays/dict/vtable/mod.rs b/vortex-array/src/arrays/dict/vtable/mod.rs index c0ca0d38dd8..6b184ac3c69 100644 --- a/vortex-array/src/arrays/dict/vtable/mod.rs +++ b/vortex-array/src/arrays/dict/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use kernel::PARENT_KERNELS; use vortex_error::VortexResult; @@ -191,7 +192,7 @@ impl VTable for DictVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { if let Some(canonical) = execute_fast_path(&array, ctx)? { return Ok(ExecutionResult::done(canonical)); } diff --git a/vortex-array/src/arrays/extension/vtable/mod.rs b/vortex-array/src/arrays/extension/vtable/mod.rs index e2b96cb64de..379fa3861a1 100644 --- a/vortex-array/src/arrays/extension/vtable/mod.rs +++ b/vortex-array/src/arrays/extension/vtable/mod.rs @@ -6,6 +6,7 @@ mod operations; mod validity; use std::hash::Hash; +use std::sync::Arc; use kernel::PARENT_KERNELS; use vortex_error::VortexExpect; @@ -149,7 +150,7 @@ impl VTable for ExtensionVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } diff --git a/vortex-array/src/arrays/filter/vtable.rs b/vortex-array/src/arrays/filter/vtable.rs index 11e475308e8..1cb736457d4 100644 --- a/vortex-array/src/arrays/filter/vtable.rs +++ b/vortex-array/src/arrays/filter/vtable.rs @@ -4,6 +4,7 @@ use std::fmt::Debug; use std::fmt::Formatter; use std::hash::Hasher; +use std::sync::Arc; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -155,7 +156,7 @@ impl VTable for FilterVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { if let Some(canonical) = execute_filter_fast_paths(&array, ctx)? { return Ok(ExecutionResult::done(canonical)); } diff --git a/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs b/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs index a7a4758598e..274ee387f7a 100644 --- a/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs +++ b/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -218,7 +219,7 @@ impl VTable for FixedSizeListVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } } diff --git a/vortex-array/src/arrays/list/vtable/mod.rs b/vortex-array/src/arrays/list/vtable/mod.rs index 7765040af8f..6ba4819b795 100644 --- a/vortex-array/src/arrays/list/vtable/mod.rs +++ b/vortex-array/src/arrays/list/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -211,9 +212,9 @@ impl VTable for ListVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( - list_view_from_list(array, ctx)?.into_array(), + list_view_from_list(ListArray::clone(&array), ctx)?.into_array(), )) } diff --git a/vortex-array/src/arrays/listview/vtable/mod.rs b/vortex-array/src/arrays/listview/vtable/mod.rs index 35e4ac994aa..33c5b527a8a 100644 --- a/vortex-array/src/arrays/listview/vtable/mod.rs +++ b/vortex-array/src/arrays/listview/vtable/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -238,7 +239,7 @@ impl VTable for ListViewVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } diff --git a/vortex-array/src/arrays/masked/vtable/mod.rs b/vortex-array/src/arrays/masked/vtable/mod.rs index 8172212ca33..36c4e41b38d 100644 --- a/vortex-array/src/arrays/masked/vtable/mod.rs +++ b/vortex-array/src/arrays/masked/vtable/mod.rs @@ -5,6 +5,7 @@ mod operations; mod validity; use std::hash::Hash; +use std::sync::Arc; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -161,7 +162,7 @@ impl VTable for MaskedVTable { MaskedArray::try_new(child, validity) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { let validity_mask = array.validity_mask()?; // Fast path: all masked means result is all nulls. diff --git a/vortex-array/src/arrays/null/mod.rs b/vortex-array/src/arrays/null/mod.rs index 8495c0074bf..f337f574a4d 100644 --- a/vortex-array/src/arrays/null/mod.rs +++ b/vortex-array/src/arrays/null/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use vortex_error::VortexResult; use vortex_error::vortex_ensure; @@ -131,7 +132,7 @@ impl VTable for NullVTable { PARENT_RULES.evaluate(array, parent, child_idx) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } } diff --git a/vortex-array/src/arrays/primitive/vtable/mod.rs b/vortex-array/src/arrays/primitive/vtable/mod.rs index 315df8450d3..95771ee6d09 100644 --- a/vortex-array/src/arrays/primitive/vtable/mod.rs +++ b/vortex-array/src/arrays/primitive/vtable/mod.rs @@ -29,6 +29,7 @@ mod validity; use std::hash::Hash; use std::hash::Hasher; +use std::sync::Arc; use vortex_buffer::Alignment; use vortex_session::VortexSession; @@ -198,7 +199,7 @@ impl VTable for PrimitiveVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } diff --git a/vortex-array/src/arrays/scalar_fn/vtable/mod.rs b/vortex-array/src/arrays/scalar_fn/vtable/mod.rs index e0f6cd0d41f..46cd0ba7ef4 100644 --- a/vortex-array/src/arrays/scalar_fn/vtable/mod.rs +++ b/vortex-array/src/arrays/scalar_fn/vtable/mod.rs @@ -8,6 +8,7 @@ use std::hash::Hash; use std::hash::Hasher; use std::marker::PhantomData; use std::ops::Deref; +use std::sync::Arc; use itertools::Itertools; use vortex_error::VortexExpect; @@ -195,7 +196,7 @@ impl VTable for ScalarFnVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { ctx.log(format_args!("scalar_fn({}): executing", array.scalar_fn)); let args = VecExecutionArgs::new(array.children.clone(), array.len); array diff --git a/vortex-array/src/arrays/shared/vtable.rs b/vortex-array/src/arrays/shared/vtable.rs index d02515c9cc2..857b0bc3739 100644 --- a/vortex-array/src/arrays/shared/vtable.rs +++ b/vortex-array/src/arrays/shared/vtable.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: Copyright the Vortex contributors use std::hash::Hash; +use std::sync::Arc; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -145,7 +146,7 @@ impl VTable for SharedVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { array .get_or_compute(|source| source.clone().execute::(ctx)) .map(ExecutionResult::done) diff --git a/vortex-array/src/arrays/slice/vtable.rs b/vortex-array/src/arrays/slice/vtable.rs index a5b3acca03c..d24fc125c08 100644 --- a/vortex-array/src/arrays/slice/vtable.rs +++ b/vortex-array/src/arrays/slice/vtable.rs @@ -6,6 +6,7 @@ use std::fmt::Formatter; use std::hash::Hash; use std::hash::Hasher; use std::ops::Range; +use std::sync::Arc; use vortex_error::VortexExpect; use vortex_error::VortexResult; @@ -155,7 +156,7 @@ impl VTable for SliceVTable { Ok(()) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { // Execute the child to get canonical form, then slice it let Some(canonical) = array.child.as_opt::() else { // If the child is not canonical, recurse. diff --git a/vortex-array/src/arrays/struct_/vtable/mod.rs b/vortex-array/src/arrays/struct_/vtable/mod.rs index 9c28907ef12..4659bf5df01 100644 --- a/vortex-array/src/arrays/struct_/vtable/mod.rs +++ b/vortex-array/src/arrays/struct_/vtable/mod.rs @@ -206,7 +206,7 @@ impl VTable for StructVTable { Ok(()) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } diff --git a/vortex-array/src/arrays/varbin/vtable/mod.rs b/vortex-array/src/arrays/varbin/vtable/mod.rs index 71421b861ae..02e4a2f1e9c 100644 --- a/vortex-array/src/arrays/varbin/vtable/mod.rs +++ b/vortex-array/src/arrays/varbin/vtable/mod.rs @@ -32,6 +32,7 @@ mod kernel; mod operations; mod validity; use std::hash::Hash; +use std::sync::Arc; use canonical::varbin_to_canonical; use kernel::PARENT_KERNELS; @@ -219,7 +220,7 @@ impl VTable for VarBinVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: Self::Array, ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done( varbin_to_canonical(&array, ctx)?.into_array(), )) diff --git a/vortex-array/src/arrays/varbinview/vtable/mod.rs b/vortex-array/src/arrays/varbinview/vtable/mod.rs index 2b080be6658..3da1abe43cc 100644 --- a/vortex-array/src/arrays/varbinview/vtable/mod.rs +++ b/vortex-array/src/arrays/varbinview/vtable/mod.rs @@ -242,7 +242,7 @@ impl VTable for VarBinViewVTable { PARENT_KERNELS.execute(array, parent, child_idx, ctx) } - fn execute(array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { Ok(ExecutionResult::done(array)) } } diff --git a/vortex-array/src/vtable/dyn_.rs b/vortex-array/src/vtable/dyn_.rs index 88938989485..f6fd0ad720f 100644 --- a/vortex-array/src/vtable/dyn_.rs +++ b/vortex-array/src/vtable/dyn_.rs @@ -212,20 +212,20 @@ fn downcast(array: &ArrayRef) -> &V::Array { .as_inner() } -/// Downcast an `ArrayRef` into an owned `V::Array`, avoiding a clone when possible. +/// Downcast an `ArrayRef` into an `Arc` without cloning. /// -/// If the `Arc` refcount is 1, the inner array is moved out without cloning. -/// Otherwise, falls back to cloning the inner array. -fn downcast_owned(array: ArrayRef) -> V::Array { +/// This is a zero-cost pointer cast leveraging the `#[repr(transparent)]` layout of +/// [`ArrayAdapter`]. +fn downcast_owned(array: ArrayRef) -> Arc { let adapter: Arc> = array .as_any_arc() .downcast::>() .ok() .vortex_expect("Failed to downcast array to expected encoding type"); - match Arc::try_unwrap(adapter) { - Ok(adapter) => adapter.into_inner(), - Err(arc) => arc.as_inner().clone(), - } + // SAFETY: ArrayAdapter is #[repr(transparent)] over V::Array, + // so Arc> and Arc have identical layout. + let raw = Arc::into_raw(adapter) as *const V::Array; + unsafe { Arc::from_raw(raw) } } impl Debug for ArrayVTableAdapter { diff --git a/vortex-array/src/vtable/mod.rs b/vortex-array/src/vtable/mod.rs index 945106fc361..8049455a6fa 100644 --- a/vortex-array/src/vtable/mod.rs +++ b/vortex-array/src/vtable/mod.rs @@ -328,6 +328,15 @@ macro_rules! vtable { } } + impl $crate::IntoArray for std::sync::Arc<[<$V Array>]> { + fn into_array(self) -> $crate::ArrayRef { + // SAFETY: ArrayAdapter is #[repr(transparent)] over V::Array, + // so Arc has identical layout to Arc>. + let raw = std::sync::Arc::into_raw(self) as *const $crate::ArrayAdapter<[<$V VTable>]>; + unsafe { std::sync::Arc::from_raw(raw) } + } + } + impl From<[<$V Array>]> for $crate::ArrayRef { fn from(value: [<$V Array>]) -> $crate::ArrayRef { use $crate::IntoArray; From b0f88569324aae4a3bc62a148d2c40f6ed3909da Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 10 Mar 2026 17:55:44 +0000 Subject: [PATCH 5/6] wip Signed-off-by: Joe Isaacs --- fuzz/src/array/mod.rs | 2 +- vortex-array/src/arrays/bool/vtable/mod.rs | 3 ++- vortex-array/src/arrays/decimal/vtable/mod.rs | 3 ++- vortex-array/src/arrays/extension/vtable/mod.rs | 3 ++- vortex-array/src/arrays/fixed_size_list/vtable/mod.rs | 3 ++- vortex-array/src/arrays/listview/vtable/mod.rs | 3 ++- vortex-array/src/arrays/null/mod.rs | 3 ++- vortex-array/src/arrays/primitive/vtable/mod.rs | 3 ++- vortex-array/src/arrays/struct_/vtable/mod.rs | 3 ++- vortex-array/src/arrays/varbinview/vtable/mod.rs | 3 ++- vortex-array/src/vtable/dyn_.rs | 11 +++++++++++ vortex-array/src/vtable/mod.rs | 9 --------- vortex-python/src/arrays/py/vtable.rs | 2 +- 13 files changed, 31 insertions(+), 20 deletions(-) diff --git a/fuzz/src/array/mod.rs b/fuzz/src/array/mod.rs index acd461c3a32..acb05fa4dc4 100644 --- a/fuzz/src/array/mod.rs +++ b/fuzz/src/array/mod.rs @@ -376,7 +376,7 @@ impl<'a> Arbitrary<'a> for FuzzArrayAction { current_array .to_canonical() .vortex_expect("to_canonical should succeed in fuzz test"), - &Mask::from_iter(mask.clone()), + &!Mask::from_iter(mask.clone()), ) .vortex_expect("mask_canonical_array should succeed in fuzz test"); // Update current_array to the result for chaining diff --git a/vortex-array/src/arrays/bool/vtable/mod.rs b/vortex-array/src/arrays/bool/vtable/mod.rs index 95a38a03854..1a6ca30eaab 100644 --- a/vortex-array/src/arrays/bool/vtable/mod.rs +++ b/vortex-array/src/arrays/bool/vtable/mod.rs @@ -39,6 +39,7 @@ use crate::hash::ArrayEq; use crate::hash::ArrayHash; use crate::stats::StatsSetRef; use crate::vtable::ArrayId; +use crate::vtable::upcast_array; vtable!(Bool); @@ -186,7 +187,7 @@ impl VTable for BoolVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } fn reduce_parent( diff --git a/vortex-array/src/arrays/decimal/vtable/mod.rs b/vortex-array/src/arrays/decimal/vtable/mod.rs index 8dcc871d89e..24289693ef1 100644 --- a/vortex-array/src/arrays/decimal/vtable/mod.rs +++ b/vortex-array/src/arrays/decimal/vtable/mod.rs @@ -42,6 +42,7 @@ use crate::hash::ArrayEq; use crate::hash::ArrayHash; use crate::stats::StatsSetRef; use crate::vtable::ArrayId; +use crate::vtable::upcast_array; vtable!(Decimal); // The type of the values can be determined by looking at the type info...right? @@ -208,7 +209,7 @@ impl VTable for DecimalVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } fn reduce_parent( diff --git a/vortex-array/src/arrays/extension/vtable/mod.rs b/vortex-array/src/arrays/extension/vtable/mod.rs index 379fa3861a1..397d1b4a18b 100644 --- a/vortex-array/src/arrays/extension/vtable/mod.rs +++ b/vortex-array/src/arrays/extension/vtable/mod.rs @@ -33,6 +33,7 @@ use crate::vtable; use crate::vtable::ArrayId; use crate::vtable::VTable; use crate::vtable::ValidityVTableFromChild; +use crate::vtable::upcast_array; vtable!(Extension); @@ -151,7 +152,7 @@ impl VTable for ExtensionVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } fn reduce_parent( diff --git a/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs b/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs index 274ee387f7a..023110156f0 100644 --- a/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs +++ b/vortex-array/src/arrays/fixed_size_list/vtable/mod.rs @@ -29,6 +29,7 @@ use crate::vtable; use crate::vtable::ArrayId; use crate::vtable::VTable; use crate::vtable::ValidityVTableFromValidityHelper; +use crate::vtable::upcast_array; use crate::vtable::validity_nchildren; use crate::vtable::validity_to_child; mod kernel; @@ -220,6 +221,6 @@ impl VTable for FixedSizeListVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } } diff --git a/vortex-array/src/arrays/listview/vtable/mod.rs b/vortex-array/src/arrays/listview/vtable/mod.rs index 33c5b527a8a..9288d95edfb 100644 --- a/vortex-array/src/arrays/listview/vtable/mod.rs +++ b/vortex-array/src/arrays/listview/vtable/mod.rs @@ -33,6 +33,7 @@ use crate::vtable; use crate::vtable::ArrayId; use crate::vtable::VTable; use crate::vtable::ValidityVTableFromValidityHelper; +use crate::vtable::upcast_array; use crate::vtable::validity_nchildren; use crate::vtable::validity_to_child; mod operations; @@ -240,7 +241,7 @@ impl VTable for ListViewVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } fn reduce_parent( diff --git a/vortex-array/src/arrays/null/mod.rs b/vortex-array/src/arrays/null/mod.rs index f337f574a4d..ab291c5489f 100644 --- a/vortex-array/src/arrays/null/mod.rs +++ b/vortex-array/src/arrays/null/mod.rs @@ -27,6 +27,7 @@ use crate::vtable::ArrayId; use crate::vtable::OperationsVTable; use crate::vtable::VTable; use crate::vtable::ValidityVTable; +use crate::vtable::upcast_array; pub(crate) mod compute; @@ -133,7 +134,7 @@ impl VTable for NullVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } } diff --git a/vortex-array/src/arrays/primitive/vtable/mod.rs b/vortex-array/src/arrays/primitive/vtable/mod.rs index 95771ee6d09..612c34f5bfb 100644 --- a/vortex-array/src/arrays/primitive/vtable/mod.rs +++ b/vortex-array/src/arrays/primitive/vtable/mod.rs @@ -40,6 +40,7 @@ use crate::hash::ArrayEq; use crate::hash::ArrayHash; use crate::stats::StatsSetRef; use crate::vtable::ArrayId; +use crate::vtable::upcast_array; vtable!(Primitive); @@ -200,7 +201,7 @@ impl VTable for PrimitiveVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } fn reduce_parent( diff --git a/vortex-array/src/arrays/struct_/vtable/mod.rs b/vortex-array/src/arrays/struct_/vtable/mod.rs index 4659bf5df01..44bcc9ed16b 100644 --- a/vortex-array/src/arrays/struct_/vtable/mod.rs +++ b/vortex-array/src/arrays/struct_/vtable/mod.rs @@ -37,6 +37,7 @@ use crate::hash::ArrayEq; use crate::hash::ArrayHash; use crate::stats::StatsSetRef; use crate::vtable::ArrayId; +use crate::vtable::upcast_array; vtable!(Struct); @@ -207,7 +208,7 @@ impl VTable for StructVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } fn reduce_parent( diff --git a/vortex-array/src/arrays/varbinview/vtable/mod.rs b/vortex-array/src/arrays/varbinview/vtable/mod.rs index 3da1abe43cc..d85c21c18d5 100644 --- a/vortex-array/src/arrays/varbinview/vtable/mod.rs +++ b/vortex-array/src/arrays/varbinview/vtable/mod.rs @@ -33,6 +33,7 @@ use crate::vtable; use crate::vtable::ArrayId; use crate::vtable::VTable; use crate::vtable::ValidityVTableFromValidityHelper; +use crate::vtable::upcast_array; use crate::vtable::validity_nchildren; use crate::vtable::validity_to_child; mod kernel; @@ -243,6 +244,6 @@ impl VTable for VarBinViewVTable { } fn execute(array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { - Ok(ExecutionResult::done(array)) + Ok(ExecutionResult::done(upcast_array::(array))) } } diff --git a/vortex-array/src/vtable/dyn_.rs b/vortex-array/src/vtable/dyn_.rs index f6fd0ad720f..09e831de7d7 100644 --- a/vortex-array/src/vtable/dyn_.rs +++ b/vortex-array/src/vtable/dyn_.rs @@ -228,6 +228,17 @@ fn downcast_owned(array: ArrayRef) -> Arc { unsafe { Arc::from_raw(raw) } } +/// Upcast an `Arc` into an `ArrayRef` without cloning. +/// +/// This is a zero-cost pointer cast leveraging the `#[repr(transparent)]` layout of +/// [`ArrayAdapter`]. It is the reverse of `downcast_owned`. +pub fn upcast_array(array: Arc) -> ArrayRef { + // SAFETY: ArrayAdapter is #[repr(transparent)] over V::Array, + // so Arc and Arc> have identical layout. + let raw = Arc::into_raw(array) as *const ArrayAdapter; + unsafe { Arc::from_raw(raw) } +} + impl Debug for ArrayVTableAdapter { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "Encoding<{}>", type_name::()) diff --git a/vortex-array/src/vtable/mod.rs b/vortex-array/src/vtable/mod.rs index 8049455a6fa..945106fc361 100644 --- a/vortex-array/src/vtable/mod.rs +++ b/vortex-array/src/vtable/mod.rs @@ -328,15 +328,6 @@ macro_rules! vtable { } } - impl $crate::IntoArray for std::sync::Arc<[<$V Array>]> { - fn into_array(self) -> $crate::ArrayRef { - // SAFETY: ArrayAdapter is #[repr(transparent)] over V::Array, - // so Arc has identical layout to Arc>. - let raw = std::sync::Arc::into_raw(self) as *const $crate::ArrayAdapter<[<$V VTable>]>; - unsafe { std::sync::Arc::from_raw(raw) } - } - } - impl From<[<$V Array>]> for $crate::ArrayRef { fn from(value: [<$V Array>]) -> $crate::ArrayRef { use $crate::IntoArray; diff --git a/vortex-python/src/arrays/py/vtable.rs b/vortex-python/src/arrays/py/vtable.rs index 9a36c89eba6..447d74367cb 100644 --- a/vortex-python/src/arrays/py/vtable.rs +++ b/vortex-python/src/arrays/py/vtable.rs @@ -156,7 +156,7 @@ impl VTable for PythonVTable { Ok(()) } - fn execute(_array: Self::Array, _ctx: &mut ExecutionCtx) -> VortexResult { + fn execute(_array: Arc, _ctx: &mut ExecutionCtx) -> VortexResult { todo!() } } From ad96dfd2616d9cf3c21732a4abb02c78e084d5a8 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 10 Mar 2026 19:09:56 +0000 Subject: [PATCH 6/6] wip Signed-off-by: Joe Isaacs --- vortex-array/src/array/mod.rs | 6 +++--- vortex-array/src/executor.rs | 9 +-------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/vortex-array/src/array/mod.rs b/vortex-array/src/array/mod.rs index 80f5114f3a6..f291aec7068 100644 --- a/vortex-array/src/array/mod.rs +++ b/vortex-array/src/array/mod.rs @@ -98,7 +98,7 @@ pub trait DynArray: fn dtype(&self) -> &DType; /// Returns the vtable of the array. - fn vtable(&self) -> &dyn DynVTable; + fn vtable(&self) -> &'static dyn DynVTable; /// Returns the encoding ID of the array. fn encoding_id(&self) -> ArrayId; @@ -192,7 +192,7 @@ impl DynArray for Arc { self.as_ref().dtype() } - fn vtable(&self) -> &dyn DynVTable { + fn vtable(&self) -> &'static dyn DynVTable { self.as_ref().vtable() } @@ -459,7 +459,7 @@ impl DynArray for ArrayAdapter { V::dtype(&self.0) } - fn vtable(&self) -> &dyn DynVTable { + fn vtable(&self) -> &'static dyn DynVTable { V::vtable() } diff --git a/vortex-array/src/executor.rs b/vortex-array/src/executor.rs index 15306032e55..ccacb3b6e8a 100644 --- a/vortex-array/src/executor.rs +++ b/vortex-array/src/executor.rs @@ -331,14 +331,7 @@ impl Executable for ArrayRef { /// /// Extracts the vtable before consuming the array to avoid borrow conflicts. fn execute_step(array: ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult { - // Extract vtable ref before the move. VTable references are &'static in practice - // (backed by const statics in ArrayVTableAdapter), so we can safely extend the lifetime. - let vtable = array.as_ref().vtable(); - // SAFETY: The vtable is always a &'static reference (see ArrayVTableAdapter::vtable), - // but the DynArray trait signature ties it to &self. We extend the lifetime to allow - // consuming the array. - let vtable: &'static dyn crate::vtable::DynVTable = - unsafe { &*(vtable as *const dyn crate::vtable::DynVTable) }; + let vtable = array.vtable(); vtable.execute(array, ctx) }