Topaz разделяет structural records и nominal record, enum, newtype, чтобы не смешивать shape полей, declaration identity, construction, update, pattern, comparison и protocol conformance.
Политика
Structural record literal содержит одно или больше field: expression; value{ field: replacement } создаёт поверхностный structural update. record Name, enum Name, newtype Name = Base — top-level nominal declarations с invariant parameters. Nominal construction использует bare declaration name. Defaults записи выполняются один раз на construction в порядке объявления после explicit fields; enum constructors находятся в namespace enum; .value() у newtype снимает один слой.
Определённое поведение
Структурное равенство сравнивает совместимые наборы полей независимо от их порядка в исходнике. Номинальное равенство сначала требует одну и ту же декларацию, затем сравнивает вариант и данные либо поля в порядке объявления. Номинальное расширение допускает ровно один начальный ...source в Name { ...source, replacements }, создаёт новое внешнее значение, вычисляет замены слева направо и не запускает значения по умолчанию повторно. Номинальный шаблон записи выбирает хотя бы одно поле и сначала проверяет тип записи.
Ограничения и явный отказ
Отклоняются JavaScript { ...value }, несколько или неведущий nominal spread, namespace-qualified brace construction, implicit this, &self, &mut self, receiver внутри record body, пустой nominal pattern, повторные/неизвестные поля и construction через затенённое имя. Structural update не является nominal update, а совпадение shape не заменяет nominal identity.
Отложенная граница
Generic derives, широкие imported-target implementations, dynamic/first-class protocol dispatch, qualified construction, open nominal patterns, reflection, inheritance и row polymorphism отложены. Receiver methods существуют только в ограниченном module-top-level impl Name с bare immutable by-value self и не импортируют Rust ownership syntax.
Пример
record User {
name: string,
age: int = 0,
}
let before: User = User { name: "Ada", age: 36 }
let after: User = User { ...before, age: 37 }
print("{before.age}:{after.age}")