Repository: pola-rs/polars
File: crates/polars-expr/src/expressions/cast.rs (Rust)

Code before:
        groups: &'a GroupPositions,
        state: &ExecutionState,
    ) -> PolarsResult<AggregationContext<'a>> {
        let mut ac = self.input.evaluate_on_groups(df, groups, state)?;

        match ac.agg_state() {
            // this will not explode and potentially increase memory due to overlapping groups
            AggState::AggregatedList(s) => {
                let ca = s.list().unwrap();
                let casted = ca.apply_to_inner(&|s| {
                    self.finish(&s.into_column())
                        .map(|c| c.take_materialized_series())
                })?;
                ac.with_values(casted.into_column(), true, None)?;
            },
            AggState::AggregatedScalar(s) => {
                let s = self.finish(&s.clone().into_column())?;
                if ac.is_literal() {
                    ac.with_literal(s);
                } else {
                    ac.with_values(s, true, None)?;
                }
            },
            AggState::NotAggregated(_) => {
                // We need to perform aggregation only for strict mode, since if this is not done,
                // a cast error may occur if the `groups` have been filtered, but this is not reflected in the `state'.
                // Otherwise, we will use `flat_naive` to improve performance.
                match self.options {
                    CastOptions::Strict => {
                        let s = ac.aggregated();
                        let ca = s.list().unwrap();
                        let casted = ca.apply_to_inner(&|s| {
                            self.finish(&s.into_column())
                                .map(|c| c.take_materialized_series())
                        })?;
                        ac.with_values(casted.into_column(), true, None)?;
                    },
                    CastOptions::NonStrict | CastOptions::Overflowing => {
                        // before we flatten, make sure that groups are updated
                        ac.groups();

                        let s = ac.flat_naive();
                        let s = self.finish(&s.as_ref().clone().into_column())?;

                        ac.with_values(s, false, None)?;
                    },
                }
            },

            AggState::LiteralScalar(s) => {
                let s = self.finish(s)?;

Review comment (bug):
```suggestion
                // filtered-out values may incorrectly cause a cast error
```


Code after:
        groups: &'a GroupPositions,
        state: &ExecutionState,
    ) -> PolarsResult<AggregationContext<'a>> {
        let mut ac = self.input.evaluate_on_groups(df, groups, state)?;

        match ac.agg_state() {
            // this will not explode and potentially increase memory due to overlapping groups
            AggState::AggregatedList(s) => {
                let ca = s.list().unwrap();
                let casted = ca.apply_to_inner(&|s| {
                    self.finish(&s.into_column())
                        .map(|c| c.take_materialized_series())
                })?;
                ac.with_values(casted.into_column(), true, None)?;
            },
            AggState::AggregatedScalar(s) => {
                let s = self.finish(&s.clone().into_column())?;
                if ac.is_literal() {
                    ac.with_literal(s);
                } else {
                    ac.with_values(s, true, None)?;
                }
            },
            AggState::NotAggregated(_) => {
                // We need to perform aggregation only for strict mode, since if this is not done,
                // filtered-out values may incorrectly cause a cast error
                // Otherwise, we will use `flat_naive` to improve performance.
                match self.options {
                    CastOptions::Strict => {
                        let s = ac.aggregated();
                        let ca = s.list().unwrap();
                        let casted = ca.apply_to_inner(&|s| {
                            self.finish(&s.into_column())
                                .map(|c| c.take_materialized_series())
                        })?;
                        ac.with_values(casted.into_column(), true, None)?;
                    },
                    CastOptions::NonStrict | CastOptions::Overflowing => {
                        // before we flatten, make sure that groups are updated
                        ac.groups();

                        let s = ac.flat_naive();
                        let s = self.finish(&s.as_ref().clone().into_column())?;

                        ac.with_values(s, false, None)?;
                    },
                }
            },

            AggState::LiteralScalar(s) => {
                let s = self.finish(s)?;