Skip to content

Consider commutativity in JavaExpression.BinaryOperation #1653

@wmdietl

Description

@wmdietl

equals treats some operations as commutative (it considers (left,right) equal to (right,left)), but hashCode() is order-dependent (Objects.hash(operationKind, left, right)). This violates the equals/hashCode contract and can break use as a map/set key. Make hashCode() commutative for commutative operators (e.g., combine operand hashes in an order-independent way), or make equals order-sensitive.

            hashCodeCache = computeHashCode();
        }
        return hashCodeCache;
    }

    /**
     * Computes a hash code consistent with equals(Object).
     *
     * <p>For commutative operations, the operand contribution must be order-independent because
     * equals(Object) considers (left, right) equal to (right, left). For non-commutative
     * operations, preserve the ordered hash.
     */
    private int computeHashCode() {
        if (isCommutative()) {
            int leftHash = left.hashCode();
            int rightHash = right.hashCode();
            int first = Math.min(leftHash, rightHash);
            int second = Math.max(leftHash, rightHash);
            return Objects.hash(operationKind, first, second);
        }
        return Objects.hash(operationKind, left, right);
    }

Originally posted by @Copilot in #1643

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions