Update documentation on Record and identical.

Smaller clean-ups.

CoreLibraryReviewExempt: Documentation only.
Change-Id: Idfe543f18927043ae8ec73e81dc7d9d333bb88df
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/294542
Reviewed-by: Erik Ernst <eernst@google.com>
Commit-Queue: Lasse Nielsen <lrn@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2023-04-13 12:35:44 +00:00 committed by Commit Queue
parent be6c10504a
commit 3e0ca136b6
16 changed files with 288 additions and 27 deletions

View file

@ -83,6 +83,7 @@
* `RegExpMatch`
* `StackTrace`
* `StringSink`
None of these declarations contained any implementation to inherit,
and are marked as `interface` to signify that they are only intended
as interfaces.
@ -93,6 +94,7 @@
* `Expando`
* `WeakReference`
* `Finalizer`
The `MapEntry` value class is restricted to enable later optimizations.
The remaining classes are tightly coupled to the platform and not
intended to be subclassed or implemented.

View file

@ -58,8 +58,8 @@ library /*isNonNullableByDefault*/;
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
// abstract final class Record {}
// sdk/lib/core/record.dart:82:22: Context: This is the type denoted by the type alias.
// abstract final class Record {
// ^
//
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:24: Error: The class 'Record' can't be used as a mixin because it isn't a mixin class nor a mixin.
@ -128,6 +128,10 @@ abstract final class _C1&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C1 extends self::_C1&Object&Record {
synthetic constructor •() → self::C1
@ -138,6 +142,10 @@ abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymou
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C2 extends self::_C2&Object&RR {
synthetic constructor •() → self::C2

View file

@ -58,8 +58,8 @@ library /*isNonNullableByDefault*/;
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
// abstract final class Record {}
// sdk/lib/core/record.dart:82:22: Context: This is the type denoted by the type alias.
// abstract final class Record {
// ^
//
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:24: Error: The class 'Record' can't be used as a mixin because it isn't a mixin class nor a mixin.
@ -128,6 +128,10 @@ abstract final class _C1&Object&Record extends core::Object implements core::Rec
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ runtimeType() → core::Type;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ hashCode() → core::int;
abstract operator /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ ==(core::Object other) → core::bool;
abstract method /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ toString() → core::String;
}
abstract class C1 extends self::_C1&Object&Record {
synthetic constructor •() → self::C1
@ -138,6 +142,10 @@ abstract final class _C2&Object&RR extends core::Object implements core::Record
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ runtimeType() → core::Type;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ hashCode() → core::int;
abstract operator /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ ==(core::Object other) → core::bool;
abstract method /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ toString() → core::String;
}
abstract class C2 extends self::_C2&Object&RR {
synthetic constructor •() → self::C2

View file

@ -58,8 +58,8 @@ library /*isNonNullableByDefault*/;
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
// abstract final class Record {}
// sdk/lib/core/record.dart:82:22: Context: This is the type denoted by the type alias.
// abstract final class Record {
// ^
//
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:24: Error: The class 'Record' can't be used as a mixin because it isn't a mixin class nor a mixin.
@ -128,6 +128,10 @@ abstract final class _C1&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C1 extends self::_C1&Object&Record {
synthetic constructor •() → self::C1
@ -138,6 +142,10 @@ abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymou
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C2 extends self::_C2&Object&RR {
synthetic constructor •() → self::C2

View file

@ -58,8 +58,8 @@ library /*isNonNullableByDefault*/;
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
// abstract final class Record {}
// sdk/lib/core/record.dart:82:22: Context: This is the type denoted by the type alias.
// abstract final class Record {
// ^
//
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:24: Error: The class 'Record' can't be used as a mixin because it isn't a mixin class nor a mixin.
@ -128,6 +128,10 @@ abstract final class _C1&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C1 extends self::_C1&Object&Record {
synthetic constructor •() → self::C1
@ -138,6 +142,10 @@ abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymou
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C2 extends self::_C2&Object&RR {
synthetic constructor •() → self::C2

View file

@ -58,8 +58,8 @@ library /*isNonNullableByDefault*/;
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
// abstract final class Record {}
// sdk/lib/core/record.dart:82:22: Context: This is the type denoted by the type alias.
// abstract final class Record {
// ^
//
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:24: Error: The class 'Record' can't be used as a mixin because it isn't a mixin class nor a mixin.
@ -119,6 +119,10 @@ abstract final class _C1&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C1 extends self::_C1&Object&Record {
synthetic constructor •() → self::C1
@ -128,6 +132,10 @@ abstract final class _C2&Object&RR = core::Object with core::Record /*isAnonymou
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class C2 extends self::_C2&Object&RR {
synthetic constructor •() → self::C2

View file

@ -58,8 +58,8 @@ library /*isNonNullableByDefault*/;
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:16: Error: 'RR' is restricted and can't be extended or implemented.
// abstract class C2 with RR {} // Error.
// ^
// sdk/lib/core/record.dart:11:22: Context: This is the type denoted by the type alias.
// abstract final class Record {}
// sdk/lib/core/record.dart:82:22: Context: This is the type denoted by the type alias.
// abstract final class Record {
// ^
//
// pkg/front_end/testcases/records/type_record_as_supertype.dart:29:24: Error: The class 'Record' can't be used as a mixin because it isn't a mixin class nor a mixin.
@ -128,6 +128,10 @@ abstract final class _C1&Object&Record extends core::Object implements core::Rec
const synthetic constructor •() → self::_C1&Object&Record
: super core::Object::•()
;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ runtimeType() → core::Type;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ hashCode() → core::int;
abstract operator /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ ==(core::Object other) → core::bool;
abstract method /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ toString() → core::String;
}
abstract class C1 extends self::_C1&Object&Record {
synthetic constructor •() → self::C1
@ -138,6 +142,10 @@ abstract final class _C2&Object&RR extends core::Object implements core::Record
const synthetic constructor •() → self::_C2&Object&RR
: super core::Object::•()
;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ runtimeType() → core::Type;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ hashCode() → core::int;
abstract operator /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ ==(core::Object other) → core::bool;
abstract method /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ toString() → core::String;
}
abstract class C2 extends self::_C2&Object&RR {
synthetic constructor •() → self::C2

View file

@ -62,6 +62,10 @@ abstract final class _A3&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class A3 extends self::_A3&Object&Record {
synthetic constructor •() → self::A3

View file

@ -62,6 +62,10 @@ abstract final class _A3&Object&Record extends core::Object implements core::Rec
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ runtimeType() → core::Type;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ hashCode() → core::int;
abstract operator /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ ==(core::Object other) → core::bool;
abstract method /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ toString() → core::String;
}
abstract class A3 extends self::_A3&Object&Record {
synthetic constructor •() → self::A3

View file

@ -62,6 +62,10 @@ abstract final class _A3&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class A3 extends self::_A3&Object&Record {
synthetic constructor •() → self::A3

View file

@ -62,6 +62,10 @@ abstract final class _A3&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class A3 extends self::_A3&Object&Record {
synthetic constructor •() → self::A3

View file

@ -52,6 +52,10 @@ abstract final class _A3&Object&Record = core::Object with core::Record /*isAnon
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
abstract mixin-stub get runtimeType() → core::Type; -> core::Record::runtimeType
abstract mixin-stub get hashCode() → core::int; -> core::Record::hashCode
abstract mixin-stub operator ==(core::Object other) → core::bool; -> core::Record::==
abstract mixin-stub method toString() → core::String; -> core::Record::toString
}
abstract class A3 extends self::_A3&Object&Record {
synthetic constructor •() → self::A3

View file

@ -62,6 +62,10 @@ abstract final class _A3&Object&Record extends core::Object implements core::Rec
const synthetic constructor •() → self::_A3&Object&Record
: super core::Object::•()
;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ runtimeType() → core::Type;
abstract get /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ hashCode() → core::int;
abstract operator /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ ==(core::Object other) → core::bool;
abstract method /* from org-dartlang-sdk:///sdk/lib/core/record.dart */ toString() → core::String;
}
abstract class A3 extends self::_A3&Object&Record {
synthetic constructor •() → self::A3

View file

@ -4,10 +4,11 @@
part of dart.core;
/// The supertype of all function types.
/// A function value.
///
/// The run-time type of a function object is a function type,
/// and as such, a subtype of [Function].
/// The `Function` class is a supertype of all *function types*, and contains
/// no values itself. All objects that implement `Function`
/// have a function type as their runtime type.
///
/// The `Function` type does not carry information about the
/// parameter signatures or return type of a function.
@ -89,7 +90,7 @@ part of dart.core;
/// Like every function type has a `call` method with its own function type,
/// the `Function` type has a special `call` member
/// which acts as if it is a method with a function type of `Function`
/// (which is not a method signature which can be expression in normal
/// (which is not a method signature which can be expressed in normal
/// Dart code).
/// ```dart
/// Function fun = (int x) => "$x";

View file

@ -4,18 +4,65 @@
part of dart.core;
/// Check whether two references are to the same object.
/// Check whether two object references are to the same object.
///
/// Dart *values*, what is stored in variables, are *object references*.
/// There can be multiple references to the same object.
///
/// A Dart object has an identity, which separates it from other objects,
/// even ones with otherwise identical state.
/// The `identical` function exposes whether two object references
/// refer to the *same* object.
///
/// If an `identical` call returns `true`, it is guaranteed that there is no
/// way to distinguish the two arguments.
/// If it returns `false`, the arguments are only known
/// to not be the same object.
///
/// A non-constant invocation of a generative (non-factory) constructor,
/// or evaluating a non-constant list, set or map literal,
/// always creates a *new* object,
/// which is not identical to any existing object.
///
/// *Constant canonicalization* ensures that the result of two compile-time
/// constant expressions which create objects with the same state,
/// also evaluate to references to the same, canonical, instance.
/// Example:
/// ```dart
/// print(identical(const <int>[1], const <int>[1])); // true
/// ```
///
/// Integers and doubles are special, they do not allow creating new instances
/// at all. If two integers are equal, they are also always identical.
/// If two doubles have the same binary representation, they are identical
/// (with caveats around [double.nan] and `-0.0` on web platforms).
///
/// [Record] values do not have a _persistent_ identity.
/// This allows compilers to split a record into its parts and rebuild it later,
/// without having to worry about creating an object with the same identity.
/// A record *may* be identical to another record with the same shape,
/// if all the corresponding fields are identical, or it may not,
/// but it is never identical to anything else.
///
/// Example:
/// ```dart
/// var o = new Object();
/// var isIdentical = identical(o, new Object()); // false, different objects.
/// isIdentical = identical(o, o); // true, same object
/// isIdentical = identical(const Object(), const Object()); // true, const canonicalizes
/// isIdentical = identical([1], [1]); // false
/// isIdentical = identical(const [1], const [1]); // true
/// isIdentical = identical(const [1], const [2]); // false
/// isIdentical = identical(2, 1 + 1); // true, integers canonicalizes
/// isIdentical = identical(o, o); // true, same object.
/// isIdentical = identical(const Object(), const Object()); // true, const canonicalizes.
/// isIdentical = identical([1], [1]); // false, different new objects.
/// isIdentical = identical(const [1], const [1]); // true.
/// isIdentical = identical(const [1], const [2]); // false.
/// isIdentical = identical(2, 1 + 1); // true, integers canonicalize.
///
/// var pair = (1, "a"); // Create a record.
/// isIdentical = identical(pair, pair); // true or false, can be either.
///
/// var pair2 = (1, "a"); // Create another(?) record.
/// isIdentical = identical(pair, pair2); // true or false, can be either.
///
/// isIdentical = identical(pair, (2, "a")); // false, not identical values.
/// isIdentical = identical(pair, (1, "a", more: true)); // false, wrong shape.
/// ```
external bool identical(Object? a, Object? b);
@ -25,7 +72,14 @@ external bool identical(Object? a, Object? b);
/// on this object, even if `hashCode` has been overridden.
///
/// This hash code is compatible with [identical],
/// which just means that it's guaranteed to be stable over time.
/// which means that it's guaranteed to give the same result every time
/// it's passed the same argument, throughout a single program execution,
/// for any *non-record* object.
///
/// The identity hash code of a [Record] is undefined,
/// because a record doesn't have a guranteed persistent identity.
/// A record values identity and identity hash code can change at any time.
///
/// ```dart import:dart:collection
/// var identitySet = HashSet(equals: identical, hashCode: identityHashCode);
/// var dt1 = DateTime.now();

View file

@ -4,8 +4,140 @@
part of dart.core;
/// The base class for all record types.
/// A record value.
///
/// The `Record` class is a supertype of all *record types*,
/// but is not itself the runtime type of any object instances
/// _(it's an abstract class)_.
/// All objects that implement `Record` has a record type as their runtime type.
///
/// A record value, described by a record type, consists of a number of fields,
/// which are each either positional or named.
///
/// Record values and record types are written similarly to
/// argument lists and simplified function type parameter lists (no `required`
/// modifier allowed, or needed, since record fields are never optional).
/// Example:
/// ```dart
/// (int, String, {bool isValid}) triple = (1, "one", isValid: true);
/// ```
/// is syntactically similar to
/// ```dart
/// typedef F = void Function(int, String, {bool isValid});
/// void callIt(F f) => f(1, "one", isValid: true);
/// ```
///
/// Every record and record type has a *shape*,
/// given by the number of positional fields and the names of named fields.
/// For example:
/// ```dart continued
/// (double value, String name, {String isValid}) another = (
/// 3.14, "Pi", isValid: "real");
/// ```
/// is another record declaration with the same *shape* (two positional fields,
/// one named field named `isValid`), but with a different type.
/// The names written on the positional fields are entirely for documentation
/// purposes, they have no effect on the program _(same as names on positional
/// parameters in function types, like `typedef F = int Function(int value);`,
/// where the identifier `value` has no effect)_.
///
/// Record values are mainly destructured using patterns, like:
/// ```dart continued
/// switch (triple) {
/// case (int value, String name, isValid: bool ok): // ....
/// }
/// ```
/// The individual fields can also be accessed using named getters,
/// using `$1`, `$2`, etc. for positional fields, and the names themselves
/// for named fields.
/// ```dart continued
/// int value = triple.$1;
/// String name = triple.$2;
/// bool ok = triple.isValid;
/// ```
/// Because of that, some identifiers cannot be used as names of named fields:
/// * The names of `Object` members: `hashCode`, `runtimeType`, `toString` and
/// `noSuchMethod`.
/// * The name of a positional getter in the same record, so `(0, $1: 0)` is
/// invalid, but `(0, $2: 0)` is valid, since there is no positional field
/// with getter `$2` in *that* record shape. _(It'll still be confusing,
/// and should be avoided in practice.)_
/// * Also, no name starting with an underscore, `_`, is allowed. Field names
/// cannot be library private.
///
/// The run-time type of a record object is a record type, and as such, a
/// subtype of [Record].
abstract final class Record {}
/// subtype of [Record], and transitively of [Object] and its supertypes.
///
/// Record values do not have a persistent [identical] behavior.
/// A reference to a record object can change *at any time* to a reference
/// to another record object with the same shape and field values.
///
/// Other than that, a record type can only be a subtype of another record
/// type with the same shape, and only if the former record type's field types
/// are subtypes of the other record type's corresponding field types.
/// That is, `(int, String, {bool isValid})` is a subtype of
/// `(num, String, {Object isValid})`, because they have the same shape,
/// and the field types are pointwise subtypes.
/// Record types with different shapes are unrelated to each other.
abstract final class Record {
/// A `Type` object representing the runtime type of a record.
///
/// The runtime type of a record is defined by the record's *shape*,
/// the number of positional fields and names of named fields,
/// and the runtime type of each of those fields.
/// (The runtime type of the record does not depend on
/// the `runtimeType` getter of its fields' values,
/// which may have overridden [Object.runtimeType].)
///
/// The `Type` object of a record type is only equal to another `Type` object
/// for a record type, and only if the other record type has the same shape,
/// and if the corresponding fields have the same types.
Type get runtimeType;
/// A hash-code compatible with `==`.
///
/// Since [operator==] is defined in terms of the `==` operators of
/// the record's field values, the hash code is also computed based on the
/// [Object.hashCode] of the field values.
///
/// There is no guaranteed order in which the `hashCode` of field values
/// is accessed.
/// It's unspecified how those values are combined,
/// other than it being consistent throughout a single program execution.
int get hashCode;
/// Checks whether [other] has the same shape and equal fields to this record.
///
/// A record is only equal to another record with the same *shape*,
/// and then only when the value of every field is equal,
/// occording to its `==`, to the corresponding field value of [other].
///
/// There is no guaranteed order in which field value equality is checked,
/// and it's unspecified whether further fields are checked after finding
/// corresponding fields which are not equal.
/// It's not even guaranteed that the order is consistent within a single
/// program execution.
///
/// As usual, be very careful around objects which break the equality
/// contract, like [double.nan] which is not equal to itself.
/// For example
/// ```dart
/// var pair = ("a", double.nan);
/// if (pair != pair) print("Oops");
/// ```
/// will print the "Oops", because `pair == pair` is defined to be equal to
/// `"a" == "a" & double.nan == double.nan`, which is false.
bool operator ==(Object other);
/// Creates a string-representation of the record.
///
/// The string representation is only intended for debugging,
/// and may differ between development and production.
/// There is no guaranteed format in production mode.
///
/// In development mode, the string will strive to be a parenthesized
/// comma separated list of field representations, where the field
/// representation is the `toString` of the value for positional fields,
/// and `someName:` followed by that for a named field named `someName`.
String toString();
}