Repository: pola-rs/polars
File: crates/polars-core/src/series/into.rs (Rust)

Code before:
                let values = arr
                    .values()
                    .iter()
                    .zip(fields.iter())
                    .map(|(values, field)| {
                        let dtype = &field.dtype;
                        let s = unsafe {
                            Series::from_chunks_and_dtype_unchecked(
                                PlSmallStr::EMPTY,
                                vec![values.clone()],
                                &dtype.to_physical(),
                            )
                            .from_physical_unchecked(dtype)
                            .unwrap()
                        };
                        s.to_arrow(0, compat_level)
                    })
                    .collect::<Vec<_>>();
                StructArray::new(
                    dt.to_arrow(compat_level),
                    arr.len(),
                    values,
                    arr.validity().cloned(),
                )
                .boxed()
            },
            // special list branch to
            // make sure that we recursively apply all logical types.
            DataType::List(inner) => {
                let ca = self.list().unwrap();
                let arr = ca.chunks[chunk_idx].clone();
                let arr = arr.as_any().downcast_ref::<ListArray<i64>>().unwrap();

                let new_values = if let DataType::Null = &**inner {
                    arr.values().clone()
                } else {
                    // We pass physical arrays and cast to logical before we convert to arrow.
                    let s = unsafe {
                        Series::from_chunks_and_dtype_unchecked(
                            PlSmallStr::EMPTY,
                            vec![arr.values().clone()],
                            &inner.to_physical(),
                        )
                        .from_physical_unchecked(inner)
                        .unwrap()
                    };

                    s.to_arrow(0, compat_level)
                };

                let dtype = self.dtype().to_arrow(compat_level);

Review comment (suggestion):
Note, for nested types, the inner field `dtype`s are now sourced from from the `dtype()` of the converted inner arrays, rather than the `inner_dtype.to_arrow()` of the field definition. This is for IPC later as the converter will return only the keys array when converting categorical to arrow.


Code after:
    pub compat_level: CompatLevel,
}

impl ToArrowConverter {
    pub fn array_to_arrow(&mut self, array: &dyn Array, dtype: &DataType) -> Box<dyn Array> {
        match dtype {
            // make sure that we recursively apply all logical types.
            #[cfg(feature = "dtype-struct")]
            DataType::Struct(fields) => {
                use arrow::array::StructArray;

                let arr: &StructArray = array.as_any().downcast_ref().unwrap();
                let values = arr
                    .values()
                    .iter()
                    .zip(fields.iter())
                    .map(|(values, field)| self.array_to_arrow(values.as_ref(), field.dtype()))
                    .collect::<Vec<_>>();

                StructArray::new(
                    ArrowDataType::Struct(
                        fields
                            .iter()
                            .map(|x| x.name())
                            .zip(values.iter().map(|x| x.dtype()))
                            .map(|(name, dtype)| ArrowField::new(name.clone(), dtype.clone(), true))
                            .collect(),
                    ),
                    arr.len(),
                    values,
                    arr.validity().cloned(),
                )
                .boxed()
            },
            DataType::List(inner) => {
                let arr: &ListArray<i64> = array.as_any().downcast_ref().unwrap();
                let new_values = self.array_to_arrow(arr.values().as_ref(), inner);

                let arr = ListArray::<i64>::new(
                    ListArray::<i64>::default_datatype(new_values.dtype().clone()),
                    arr.offsets().clone(),
                    new_values,
                    arr.validity().cloned(),
                );
                Box::new(arr)
            },
            #[cfg(feature = "dtype-array")]
            DataType::Array(inner, width) => {
                use arrow::array::FixedSizeListArray;

                let arr: &FixedSizeListArray = array.as_any().downcast_ref().unwrap();