Skip to content

Let Column<L> be used where &[L::Native] is expected - #43

Merged
emilk merged 1 commit into
release-0.6from
emilk/column-as-ref
Aug 27, 2026
Merged

Let Column<L> be used where &[L::Native] is expected#43
emilk merged 1 commit into
release-0.6from
emilk/column-as-ref

Conversation

@emilk

@emilk emilk commented Aug 27, 2026

Copy link
Copy Markdown
Member

Related

What

Deref<Target = [L::Native]> and AsRef<[L::Native]> for the columns that already have as_slice (primitive and fixed-size binary, non-nullable), plus the same pair on TypedArray. A Column<u64> is now a drop-in for the ScalarBuffer<u64> it replaces, so &self.chunk_byte_sizes keeps compiling.

On the shadowing hazard raised in the issue: an inherent method wins over a dereferenced one, so iter, len, get, and to_vec still read the logical values. Indexing stays with the existing Index<usize> impl, which means range slicing needs an explicit &(*column)[a..b] — documented, and pinned by the test.

Testing

cargo test --all-features. New deref_to_slice test covers the coercion, AsRef, the slice window after Column::slice, a non-numeric native, and every method that could have been shadowed.

Compatibility

Additive. New inherent-vs-deref resolution can only change what compiles today if a caller relied on a slice method that Column does not have, which is impossible before this PR.

`Deref<Target = [L::Native]>` and `AsRef<[L::Native]>` for the columns that
already have `as_slice` (primitive and fixed-size binary, non-nullable), so a
`Column<u64>` is a drop-in for the `ScalarBuffer<u64>` it replaces and
`&self.chunk_byte_sizes` keeps compiling.

Method resolution keeps `Column`'s own methods: an inherent method wins over a
dereferenced one, so `iter`, `len`, `get`, and `to_vec` still read the logical
values. Indexing stays with the existing `Index<usize>` impl, so range slicing
needs an explicit `&(*column)[a..b]` — documented, and covered by the test.

Same pair on `TypedArray`.

Closes #40

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@emilk
emilk marked this pull request as ready for review August 27, 2026 18:39
@emilk
emilk merged commit 0259f61 into release-0.6 Aug 27, 2026
6 checks passed

@emilk emilk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Post-merge review, as part of reviewing the 0.6 stack for #30. Clippy and tests are clean at the tip of release-0.6. Not implementing DerefMut is the most important decision here — the slice stays read-only, so nothing can sort/fill/swap a validated column out from under its invariants. I also verified the FixedSizeBinary claim: arrow normalizes value_data in both slice and From<ArrayData>, so (*column).len() == column.len() always holds and the comment asserting it is correct.

The hazard isn't today's shadowing, it's tomorrow's. The body's analysis of current resolution is right — inherent wins, iter/len/get/to_vec still read the column. But today column.first() resolves through the deref to Option<&L::Native> while column.get(0) is inherent and gives Option<L::Value<'_>>. The day someone adds an inherent Column::first() returning Option<L::Value> — for symmetry with get, which is exactly why they would — every existing column.first() call site silently changes type and meaning, with no deprecation and no error wherever the two coerce.

AsRef alone has none of that, and column.as_ref() is barely longer than &column. If Deref stays (the ScalarBuffer migration case is real), write the rule next to the impl — Column never gains an inherent method whose name [T] already has — and extend the test, which is already the enforcement mechanism, to assert first/last/contains/chunks/windows with the slice-flavored types they currently return. Then CI speaks up the day someone adds an inherent one.

Combined with #41, one column reports two element types. get(0)Option<&[u8; 16]> against first()Option<&ChunkId>; column[0] against (*column)[0]. Root cause is #41's Native = Self while RefType::Ref stays the repr (substantive note left there) — this Deref is what makes the second set reachable by a method call that looks like it belongs to the first.

— Claude

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant