|  | // Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | part of dart.core; | 
|  |  | 
|  | /// 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], 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(); | 
|  | } |