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

Code before:
            Array(_, _) => bail_invalid_ineq!(lhs, rhs, $op),
            #[cfg(feature = "dtype-struct")]
            Struct(_) => bail_invalid_ineq!(lhs, rhs, $op),

            dt => polars_bail!(InvalidOperation: "could not apply comparison on series of dtype '{}'; operand names: '{}', '{}'", dt, lhs.name(), rhs.name()),
        };
        out.rename(lhs.name().clone());
        PolarsResult::Ok(out)
    }};
}

fn validate_types(left: &DataType, right: &DataType) -> PolarsResult<()> {
    use DataType::*;

    match (left, right) {
        (String, dt) | (dt, String) if dt.is_primitive_numeric() => {
            polars_bail!(ComputeError: "cannot compare string with numeric type ({})", dt)
        },
        #[cfg(feature = "dtype-categorical")]
        (Categorical(_, _) | Enum(_, _), dt) | (dt, Categorical(_, _) | Enum(_, _))
            if !(dt.is_categorical() | dt.is_string() | dt.is_enum()) =>
        {
            polars_bail!(ComputeError: "cannot compare categorical with {}", dt)
        },
        #[cfg(feature = "dtype-duration")]
        (Date, dt) | (dt, Date) if dt.is_duration() => {
            polars_bail!(ComputeError: "cannot compare date with {}", dt)
        },
        _ => (),
    };
    Ok(())
}

impl ChunkCompareEq<&Series> for Series {
    type Item = PolarsResult<BooleanChunked>;

    /// Create a boolean mask by checking for equality.
    fn equal(&self, rhs: &Series) -> Self::Item {
        impl_eq_compare!(self, rhs, equal)
    }

    /// Create a boolean mask by checking for equality.
    fn equal_missing(&self, rhs: &Series) -> Self::Item {
        impl_eq_compare!(self, rhs, equal_missing)
    }

    /// Create a boolean mask by checking for inequality.
    fn not_equal(&self, rhs: &Series) -> Self::Item {
        impl_eq_compare!(self, rhs, not_equal)
    }


Review comment (suggestion):
Can't this just be `(Date, Duration(_)) | (Duration(_), Date)`? We should always prefer direct matches over match guards if possible.

Code after:
            Array(_, _) => bail_invalid_ineq!(lhs, rhs, $op),
            #[cfg(feature = "dtype-struct")]
            Struct(_) => bail_invalid_ineq!(lhs, rhs, $op),

            dt => polars_bail!(InvalidOperation: "could not apply comparison on series of dtype '{}'; operand names: '{}', '{}'", dt, lhs.name(), rhs.name()),
        };
        out.rename(lhs.name().clone());
        PolarsResult::Ok(out)
    }};
}

fn validate_types(left: &DataType, right: &DataType) -> PolarsResult<()> {
    use DataType::*;

    match (left, right) {
        (String, dt) | (dt, String) if dt.is_primitive_numeric() => {
            polars_bail!(ComputeError: "cannot compare string with numeric type ({})", dt)
        },
        #[cfg(feature = "dtype-categorical")]
        (Categorical(_, _) | Enum(_, _), dt) | (dt, Categorical(_, _) | Enum(_, _))
            if !(dt.is_categorical() | dt.is_string() | dt.is_enum()) =>
        {
            polars_bail!(ComputeError: "cannot compare categorical with {}", dt)
        },
        #[cfg(feature = "dtype-duration")]
        (Date, Duration(_)) | (Duration(_), Date) => {
            polars_bail!(ComputeError: "cannot compare date with duration")
        },
        _ => (),
    };
    Ok(())
}

impl ChunkCompareEq<&Series> for Series {
    type Item = PolarsResult<BooleanChunked>;

    /// Create a boolean mask by checking for equality.
    fn equal(&self, rhs: &Series) -> Self::Item {
        impl_eq_compare!(self, rhs, equal)
    }

    /// Create a boolean mask by checking for equality.
    fn equal_missing(&self, rhs: &Series) -> Self::Item {
        impl_eq_compare!(self, rhs, equal_missing)
    }

    /// Create a boolean mask by checking for inequality.
    fn not_equal(&self, rhs: &Series) -> Self::Item {
        impl_eq_compare!(self, rhs, not_equal)
    }