Skip to content

SProductField overrides equals on (name, schema) without a matching hashCode #5220

@haskiindahouse

Description

@haskiindahouse

sttp.tapir.SchemaType.SProductField overrides equals to compare by (name, schema), but inherits Object.hashCode. The equals / hashCode contract requires equal objects to share a hash code, so any use of SProductField as a Map key, in a Set, or via .distinct will silently misbehave.

Source:

override def equals(other: Any): Boolean = other match {
case p: SProductField[?] => p.name == name && p.schema == schema
case _ => false
}

trait SProductField[T] extends Serializable {
  type FieldType
  def name: FieldName
  def schema: Schema[FieldType]
  def get: T => Option[FieldType]

  override def equals(other: Any): Boolean = other match {
    case p: SProductField[?] => p.name == name && p.schema == schema
    case _                   => false
  }
  // no hashCode override
}

Two SProductFields with the same (name, schema) come back as equals == true but with different identity-based hashCodes, so a HashMap[SProductField[_], V] won't find an existing key, and a hash-bucketed Set won't dedup them.

Suggested fix — keep equals as it is, add a matching hashCode:

override def hashCode(): Int = (name, schema).##

Happy to PR with a small unit test that hashes/dedups two equal SProductField instances.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions