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
    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