Skip to content

Record representation is unstable #7031

@cometkim

Description

@cometkim

Since we added support for optional fields on records, a crucial assumption was broken: up until then, records can be expected to have a fixed layout, as its definition.

So records with the same values for the same keys always had the same hash.

However, by introducing optional fields, we can easily create values ​​that pass the equality check but have different hashes.

type t = {
  a: string,
  b?: string,
  c: string,
}

let v1 = {
  a: "a",
  c: "c",
}

let v2 = {
  ...v1,
  b: "b",
}

let v3 = {
  a: "a",
  b: "b",
  c: "c"
}

assert (Hashtbl.hash(v2) == Hashtbl.hash(v3))

https://rescript-lang.org/try?version=v11.1.4&code=C4TwDgpgBMULxQN4CgpQIYC4oGdgCcBLAOwHMAaVKAIwH5s8izK0BjBgki5AX2WQA2EWADcAjPCRUsUAETpZLKOzmtFvfkNEAmSSjQA6I+KXVss6ur6DhUEQGY908wtPnLSlbLWVr6HDgQ+MAAFAAS-gAWwNQCBpFRIeIAlPAIETjRsfGJDsnJyEA

v2 and v3 have the same values for the same keys but in different order.

  • Obj.entries(v2) => [['a', 'a'], ['c', 'c'], ['b', 'b']]
  • Obj.entries(v3) => [['a', 'a'], ['b', 'b'], ['c', 'c']]

This literally means that users can't use a record as a key in a hashtable or other data structure. In other words, it's not a record.

Metadata

Metadata

Assignees

No one assigned

    Labels

    staleOld issues that went stale

    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