Equals Signature Correct

ID

kotlin.equals_signature_correct

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Code Smell

Language

Kotlin

Tags

CWE:581, correctness, reliability

Description

Reports override fun equals(other: T) declarations where the parameter type is not Any?. Such a method overloads Any.equals rather than overriding it. Collections and other framework code still use the inherited reference-equality from Any.

Rationale

Any.equals has the signature fun equals(other: Any?): Boolean. Declaring fun equals(other: MyType): Boolean creates a new overload, not an override. Two distinct methods exist at runtime: the correct one (inherited, reference-equality) and the new one (structural equality). Collections only ever call the Any? version.

// Bad — overloads, does not override
class Widget(val id: Int) {
    override fun equals(other: Widget): Boolean = id == other.id
}

val set = hashSetOf(Widget(1))
set.contains(Widget(1))  // calls Any.equals — returns false

// Good — correct signature
class Widget(val id: Int) {
    override fun equals(other: Any?): Boolean = other is Widget && id == other.id
    override fun hashCode() = id
}

The override keyword generates a compiler warning, not an error, when the parameter type does not match any parent method — so the mistake compiles silently.

Remediation

Change the parameter type to Any? and add an is check at the top of the body. Also add override fun hashCode() to satisfy the equals/hashCode contract. Consider replacing the class with a data class when it is a simple value holder.