Let Column<L> be used where &[L::Native] is expected - #43
Conversation
`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>
There was a problem hiding this comment.
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
Related
Column<L>be used where&[L::Native]is expected (Deref/AsRef) #40What
Deref<Target = [L::Native]>andAsRef<[L::Native]>for the columns that already haveas_slice(primitive and fixed-size binary, non-nullable), plus the same pair onTypedArray. AColumn<u64>is now a drop-in for theScalarBuffer<u64>it replaces, so&self.chunk_byte_sizeskeeps compiling.On the shadowing hazard raised in the issue: an inherent method wins over a dereferenced one, so
iter,len,get, andto_vecstill read the logical values. Indexing stays with the existingIndex<usize>impl, which means range slicing needs an explicit&(*column)[a..b]— documented, and pinned by the test.Testing
cargo test --all-features. Newderef_to_slicetest covers the coercion,AsRef, the slice window afterColumn::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
Columndoes not have, which is impossible before this PR.