apache / apache/arrow-rs

can_cast_types reports Interval -> Int64 as supported, but cast has no such arm

Closed Beginner friendly
#10,938 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
3.6k
Forks
1.3k
Avg merge
2d 18h
Merged PRs (30d)
169

Description

### Describe the bug

`can_cast_types` returns `true` for `Interval(YearMonth) -> Int64` and `Interval(DayTime) -> Int64`, but `cast_with_options` has no arm for either and returns `CastError`.

`can_cast_types` at `arrow-cast/src/cast/mod.rs:324-330`; the only `Interval`/integer arm in `cast_with_options` is `(Int32, Interval(YearMonth))` at `mod.rs:2312`, so both fall through to the catch-all `Err`.

Both sides were added together in #1196. #5769 made `IntervalDayTime` and `IntervalMonthDayNano` structured types and its description lists "Remove cast support from the Int64Arrays to/from those types" — the `cast` side went, the `can_cast_types` arm stayed.

This is reachable beyond the API check. `cast/union.rs::resolve_child_array` picks the first union child that `can_cast_types` accepts, so a union with an interval child and a `Utf8` child fails to cast to `Int64` even though the `Utf8` child casts fine.

### To Reproduce

```rust
use arrow_array::{ArrayRef, IntervalYearMonthArray};
use arrow_cast::{can_cast_types, cast};
use arrow_schema::{DataType, IntervalUnit};
use std::sync::Arc;

assert!(can_cast_types(
&DataType::Interval(IntervalUnit::YearMonth),
&DataType::Int64
));
let a: ArrayRef = Arc::new(IntervalYearMonthArray::from(vec![12]));
cast(&a, &DataType::Int64).unwrap();
// CastError("Casting from Interval(YearMonth) to Int64 not supported")
```

Same for `Interval(DayTime)`. `Interval(MonthDayNano)` already reports `false`.

### Expected behavior

`can_cast_types` and `cast` agree. No interval unit has an unambiguous `i64` value, so making `can_cast_types` return `false` matches #5769's intent — but implementing the cast instead is a defensible alternative if you would rather have it.

### Additional context

`arrow/tests/array_cast.rs::test_can_cast_types` exists to keep the two in sync and does not catch this, because `Int64` is missing from `get_all_types()`: lines 505-514 read `Int8, Int16, Int32, UInt64, UInt8, UInt16, UInt32, UInt64`, with `UInt64` in `Int64`'s slot and then again in its own. Line 568 of the same file has the intended sequence. Restoring `Int64` makes that test fail on main, and it is the only mismatch restoring it exposes.

Investigated with AI assistance (Claude Opus 4.8); the repro above was run against `c44f8d4`.

Contributor guide

Open the contributing guide

Research direction

Start with arrow-cast/src/cast/mod.rs:324-330 and the cast_with_options arms around mod.rs:2312, then inspect cast/union.rs::resolve_child_array. Restore Int64 in arrow/tests/array_cast.rs::get_all_types and run test_can_cast_types; done means can_cast_types and cast agree for all interval units, including union resolution.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
data
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
85/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.