can_cast_types reports Interval -> Int64 as supported, but cast has no such arm
- 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
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