Repository: pola-rs/polars
File: crates/polars-plan/src/plans/visitor/hash.rs (Rust)

Code before:
    }
}

#[cfg(feature = "python")]
fn pred_eq(
    l: &crate::prelude::PythonPredicate,
    r: &crate::prelude::PythonPredicate,
    expr_arena: &Arena<AExpr>,
) -> bool {
    use crate::prelude::PythonPredicate;
    match (l, r) {
        (PythonPredicate::None, PythonPredicate::None) => true,
        (PythonPredicate::PyArrow(a), PythonPredicate::PyArrow(b)) => a == b,
        (PythonPredicate::Polars(a), PythonPredicate::Polars(b)) => expr_ir_eq(a, b, expr_arena),
        _ => false,
    }
}

impl Hash for HashableEqLP<'_> {
    // This hashes the variant, not the whole plan
    fn hash<H: Hasher>(&self, state: &mut H) {
        let alp = self.node.to_alp(self.lp_arena);
        std::mem::discriminant(alp).hash(state);
        match alp {
            #[cfg(feature = "python")]
            IR::PythonScan { options } => {
                // Hash the Python function object using the pointer to the object
                // This should be the same as calling id() in python, but we don't need the GIL
                if let Some(scan_fn) = &options.scan_fn {
                    let ptr_addr = scan_fn.0.as_ptr() as usize;
                    ptr_addr.hash(state);
                }
                // Hash the stable fields
                // We include the schema since it can be set by the user
                options.schema.hash(state);
                options.output_schema.hash(state);
                options.with_columns.hash(state);
                options.python_source.hash(state);
                options.n_rows.hash(state);
                hash_python_predicate(&options.predicate, self.expr_arena, state);
                options.validate_schema.hash(state);
            },
            IR::Slice {
                offset,
                len,
                input: _,
            } => {
                len.hash(state);
                offset.hash(state);
            },
            IR::Filter {

Review comment (bug):
Could we use destructuring syntax here - 

```rust
IR::PythonScan { options: PythonOptions { scan_fn, (etc.) } }
```

This will add safety by ensuring that compilation fails in case a new field is added in the future.


Code after:
        PythonPredicate::PyArrow(s) => s.hash(state),
        PythonPredicate::Polars(e) => e.traverse_and_hash(expr_arena, state),
    }
}

#[cfg(feature = "python")]
fn pred_eq(
    l: &crate::prelude::PythonPredicate,
    r: &crate::prelude::PythonPredicate,
    expr_arena: &Arena<AExpr>,
) -> bool {
    use crate::prelude::PythonPredicate;
    match (l, r) {
        (PythonPredicate::None, PythonPredicate::None) => true,
        (PythonPredicate::PyArrow(a), PythonPredicate::PyArrow(b)) => a == b,
        (PythonPredicate::Polars(a), PythonPredicate::Polars(b)) => expr_ir_eq(a, b, expr_arena),
        _ => false,
    }
}

impl Hash for HashableEqLP<'_> {
    // This hashes the variant, not the whole plan
    fn hash<H: Hasher>(&self, state: &mut H) {
        let alp = self.node.to_alp(self.lp_arena);
        std::mem::discriminant(alp).hash(state);
        match alp {
            #[cfg(feature = "python")]
            IR::PythonScan {
                options:
                    PythonOptions {
                        scan_fn,
                        schema,
                        output_schema,
                        with_columns,
                        python_source,
                        n_rows,
                        predicate,
                        validate_schema,
                        is_pure,
                    },
            } => {
                // Hash the Python function object using the pointer to the object
                // This should be the same as calling id() in python, but we don't need the GIL
                if let Some(scan_fn) = scan_fn {
                    let ptr_addr = scan_fn.0.as_ptr() as usize;
                    ptr_addr.hash(state);
                }
                // Hash the stable fields
                // We include the schema since it can be set by the user
                schema.hash(state);
                output_schema.hash(state);