@@ -322,38 +322,39 @@ through calls to `identical()`, then optimizing away the creation of these
322
322
objects is harder.
323
323
324
324
Semantically, we do not want records to have unique identities distinct from
325
- their contents. A record * is* its contents in the same way that every value 3
326
- in a program is the "same" 3 whether it came from the number literal ` 3 ` or the
327
- result of ` 1 + 2 ` .
325
+ their contents. A record * is* its contents in the same way that every value 3 in
326
+ a program is the "same" 3 whether it came from the number literal ` 3 ` or the
327
+ result of ` 1 + 2 ` . This is why ` == ` for records is defined in terms of their
328
+ shape and fields. Two records with the same shape and equal fields are equal
329
+ values.
328
330
329
- This is why ` == ` for records is defined in terms of their shape and fields. Two
330
- records with the same shape and fields are equivalent. Identity follows similar
331
- rules. Calling ` identical() ` with a record argument returns:
331
+ At the same time, we want ` identical() ` to be fast because one of its primary
332
+ uses is as a fast-path check for equality. An ` identical() ` that is obliged to
333
+ iterate over the record's fields (transitively in the case where some fields
334
+ are themselves records) might nullify the benefits of using ` identical() ` as a
335
+ fast-path check before calling ` == ` .
336
+
337
+ To balance those opposing goals, ` identical() ` on records is defined to only
338
+ offer loose guarantees. Calling ` identical() ` with a record argument returns:
332
339
333
340
* ` false ` , if the other argument is not a record.
334
341
* ` false ` , if the records do not have the same shape. * Since named field
335
342
order is not part of a record's shape, this implies that named field order
336
- does not affect identity either. ` ( a: 1, b: 2)` and ` (b: 2, a: 1) ` are
337
- identical .*
343
+ does not affect identity either. ` identical(( a: 1, b: 2), (b: 2, a: 1)) ` is
344
+ not required to return false .*
338
345
* ` false ` , if any pair of corresponding fields are not identical.
339
- * Otherwise ` true ` .
340
-
341
- This means ` identical() ` on records is structural and recursive. However, since
342
- records are immutable and ` identical() ` on other aggregate types does not
343
- recurse into fields, it cannot be * cyclic.*
344
-
345
- An important use case for ` identical() ` is as a fast path check for equality.
346
- It's common to use ` identical() ` to quickly see if two objects are "the same",
347
- and if so avoid the potentially slower call to ` == ` . We have some concern that
348
- structural rules for ` identical() ` of records could be slow.
349
-
350
- We will coordinate with the implementation teams and if they are not confident
351
- that they can get reasonable performance out of it, we may change these rules
352
- before accepting the proposal. "Reasonable" here means fast enough that users
353
- won't find themselves wishing for some other specialized ` reallyIdentical() `
354
- function that avoids the cost of structural ` identical() ` checks on records.
355
-
356
- ** TODO: Discuss with implementation teams.**
346
+ * Otherwise it * may* return ` true ` , but is not required to.
347
+
348
+ * If an implementation can easily determine that two record arguments to
349
+ ` identical() ` have the same shape and identical fields, then it should return
350
+ ` true ` . Typically, this is because the two arguments to ` identical() ` are
351
+ pointers with the same address to the same heap-allocated record object. But if
352
+ an implementation would have to do a slower field-wise comparison to determine
353
+ identity, it's probably better to return ` false ` quickly.*
354
+
355
+ * In other words, if ` identical() ` returns ` true ` , then the records are
356
+ definitely indistinguishable. But if it returns ` false ` , they may or may not
357
+ be.*
357
358
358
359
#### Expandos
359
360
0 commit comments