Перейти к содержимому
Топаз6.0 · До релиза
Загрузка →

Поиск в документации

Спецификация 6.0

Выберите результат стрелками и нажмите Enter, чтобы открыть его.

Введите имя API, номер диагностики, правило или тему проекта.

    Язык · 8 глав · 43 правила

    Протоколы и реализации

    Declare protocol requirements, provide implementations, and understand conformance, receiver methods, and resource bindings.

    Scope and ownership

    Ссылка

    Use this page to declare protocol requirements, implement them, and add receiver methods.

    This page owns protocol declarations, implementation conformance, protocol resolution, receiver self, and using.

    Records, enums and newtypes owns nominal declarations and derives placement. Functions and generics owns ordinary function signatures, calls, and bound syntax. Standard library entries own the behavior of built-in methods.

    Declaration forms

    Ссылка
    EBNF
    1. ProtocolDeclaration =
    2. "export"? "protocol" Identifier
    3. "{" ProtocolSignature* "}" ;
    4. ProtocolSignature =
    5. "function" Identifier FunctionTypeParameters?
    6. "(" FunctionParameters? ")" ("->" Type)? ;
    7. Implementation =
    8. "impl" FunctionTypeParameters? NamedType
    9. "{" ImplementationMethod* "}" ;
    10. ImplementationMethod =
    11. "export"? NamedFunction ;
    12. ProtocolReference = Identifier ("." Identifier)? ;
    13. UsingStatement =
    14. "using" Identifier "=" ControlOperand Block ;
    15. ConditionalDerivesClause =
    16. "derives" FunctionTypeParameters ProtocolReference "<" Type ">"
    17. ("," ProtocolReference "<" Type ">")* ;

    An export prefix publishes a module-level protocol declaration. Protocol references in bounds and conformance clauses use P or ns.P through the ordinary import boundary. One implementation head uses the ordinary named-type and type-argument grammar. Name resolution distinguishes a protocol application, which takes one conforming type, from a nominal receiver. Explicit binders precede either head. Protocol signatures use ordinary annotated parameters; their result annotation is required during checking. A conditional derives clause appears before the nominal body or newtype base.

    Правилоtopaz.rule.structures.protocols.declaration.body

    Protocol bodies

    A protocol body contains function signatures.

    Причина

    A protocol states required operations independently of their implementations. Signatures give callers a contract without choosing the code that provides it.

    Правилоtopaz.rule.structures.protocols.implementation.form

    Protocol implementation form

    impl Protocol<Type> supplies definitions for one protocol and a complete conforming type. An explicit binder list precedes the protocol name for a conditional implementation. The protocol application has exactly one conforming type argument. Type aliases are expanded, and generic heads match the resolved static type through type equality, not value subtyping. A protocol call chooses the conformance before execution.

    Причина

    Naming the resolved protocol and target type identifies one contract. Using the ordinary type grammar admits built-in, structural, and nominal targets without a new implementation notation.

    Правилоtopaz.rule.structures.protocols.receiver.form

    Receiver implementation form

    impl Type declares receiver methods for a nominal type owned by the current module. For a generic receiver, write explicit binders before its complete target, as in impl<T> Box<T>. Those binders enter method signatures and bodies; a method may introduce its own nested binders. The first bare self retains the instantiated receiver type even if a method binder shadows an outer name. The existing receiver name, field-collision, and export rules apply to every instantiation.

    Причина

    Receiver methods already identify their type through the receiver expression. Explicit enclosing binders let generic receivers use the same method declarations and calls as concrete receivers.

    Protocol method requirements

    Ссылка
    Правилоtopaz.rule.structures.protocols.declaration.parameter-count

    Protocol declarations use Self

    A protocol declaration has no explicit type parameter list. Use Self for its conforming type. An explicit receiver binder is rejected during parsing with TPZ2001.

    Причина

    An explicit receiver binder and Self both name the type that implements the protocol. The binder renames that role rather than introducing a different type relationship. Self preserves the same receiver intent and matches built-in protocol signatures.

    Правилоtopaz.rule.structures.protocols.signature.conforming-type

    The conforming type in signatures

    Within a protocol method signature, Self denotes the conforming type.

    Причина

    The conforming type must be substituted consistently throughout a protocol signature. This keeps its receiver and related arguments tied to the same implementation target.

    Правилоtopaz.rule.structures.protocols.signature.first-parameter

    Selecting the conforming type

    A protocol method has an implicit conforming type parameter named Self. It may occur in any parameter or result type. Methods may have no value parameters. A call infers Self from its arguments and expected result through the ordinary generic-call rules. An explicit call type-argument list supplies Self first, followed by the method parameters. Dispatch requires one resolved conforming type; a call without enough inference evidence must supply that complete list.

    Причина

    A constructor or decoder has no existing receiver value. Selecting the conforming type with the ordinary generic-call rules makes the same protocol operation usable before and after a value exists. No position in a value-parameter list owns dispatch.

    Правилоtopaz.rule.structures.protocols.signature.return-annotation

    Protocol return annotation

    Every protocol method requires an explicit return annotation, including -> () for unit. An omitted annotation produces TPZ5022.

    Причина

    A protocol signature has no body from which to infer a result. An explicit result type gives callers and implementations the same complete contract.

    Правилоtopaz.rule.structures.protocols.signature.parameter-restrictions

    Ordinary function parameters in protocols

    Protocol signatures use the type parameter, bound, annotated parameter, variadic, and default-expression rules of named functions. Method binders are distinct from implicit Self and are in scope throughout that method signature, including bounds and result types. They do not enter another method. Parameters remain immutable. Required fixed parameters precede the defaulted suffix; one final variadic parameter has no default and binds an array. The protocol declaration owns each default. Its names resolve in the protocol declaration environment, where value parameters are unavailable. Supplied arguments and omitted defaults follow ordinary call evaluation order.

    The method type parameters follow implicit Self in the generic call signature. Implementation signature matching compares their resolved types and bounds after renaming corresponding binders. Protocol declarations have no body, so the result annotation remains required.

    Причина

    A protocol promises callable operations. Giving those operations the same generic, variadic, and omission rules as named functions avoids a parallel helper-function interface. Keeping defaults in that promise gives every implementation and caller one omission behavior.

    Правилоtopaz.rule.structures.protocols.declaration.unique-name

    Unique protocol names

    Redeclaring a user protocol name in the same module produces TPZ3008 during resolution.

    Причина

    A protocol name must identify one contract in its module. Reusing the name would make conformance declarations ambiguous.

    Правилоtopaz.rule.structures.protocols.signature.unique-name

    Unique protocol method names

    Declaring the same method name twice in a protocol produces TPZ5008.

    Причина

    A method name must identify one operation within a protocol. Duplicate names would make implementation coverage and calls ambiguous.

    Правилоtopaz.rule.structures.protocols.declaration.builtin-names

    Built-in protocol names

    Redeclaring the built-in protocols Eq, Order, Show, or JSON produces TPZ5008.

    Причина

    Built-in operations and bounds use these protocol names. Redeclaring them could change the meaning of existing equality, ordering, display, or serialization code.

    Правилоtopaz.rule.structures.protocols.declaration.type-name-collision

    Protocol and type name collisions

    Reusing a declared type name for a protocol in the same module produces TPZ3008 during resolution.

    Причина

    Protocol and type names occur in implementation heads. Distinct names keep an implementation target from being mistaken for its protocol.

    Правилоtopaz.rule.structures.protocols.declaration.module-context

    Module-level declarations

    A protocol or implementation declaration inside a block produces TPZ5022.

    Причина

    Conformance is checked for the program before execution. Module declarations keep the available implementation from depending on whether a block has executed.

    Implementation conformance

    Ссылка
    Правилоtopaz.rule.structures.protocols.implementation.target

    Implementation ownership

    The implementing module must define either the resolved protocol or the target type's outermost nominal declaration. A module may therefore define its own protocol for int, string, a structural type, or a generic type pattern. A foreign protocol requires an own-module record, enum, or newtype as the target's outermost constructor. A local type argument inside a foreign Array or Map does not transfer ownership. Transparent aliases preserve the underlying type and its owner. Implementing a foreign protocol for a foreign type produces TPZ5520. Every admitted implementation also passes the complete dependency graph's uniqueness check.

    Причина

    The protocol owner can give an existing type a new operation without inventing a wrapper or a separate helper-function interface. The type owner can adopt an existing operation. Requiring one of those owners and rejecting graph-wide overlap gives each protocol and target pair one meaning.

    Правилоtopaz.rule.structures.protocols.implementation.method-coverage

    Required implementation methods

    An implementation supplies every declared protocol method and no undeclared method. A missing or undeclared method produces TPZ5022.

    Причина

    Every operation promised by a protocol must be callable. Rejecting extra methods also catches a misspelled implementation name instead of leaving the intended operation missing.

    Правилоtopaz.rule.structures.protocols.implementation.unique-method

    Unique implementation methods

    Implementing the same method twice in a protocol implementation produces TPZ5008.

    Причина

    One implementation must supply one definition for each operation. Repeated definitions would make dispatch depend on declaration order.

    Правилоtopaz.rule.structures.protocols.implementation.signature

    Matching the protocol signature

    Substitute the complete target for Self, keep implementation binders rigid, and pair method binders by position. Method binder counts, their sets of resolved protocol bounds, fixed parameter types, variadic position and element type, and result type must match. Type aliases and binder names do not create differences; bound order and parameter names do not affect a positional call. Repeated bounds still follow the ordinary duplicate-bound rule. The implementation may neither strengthen nor weaken a method's bound set. An explicit result annotation must equal the protocol result. When it is omitted, use the protocol result as the ordinary expected result while checking the body. Each return and tail must be assignable to that result; omission does not narrow the public signature. A signature mismatch produces TPZ5022.

    Причина

    Callers have one complete signature before they see an implementation. Alpha-equivalence allows harmless renaming, while exact callable structure and bound identity preserve the same obligations. The protocol already supplies the result context, so repeating its annotation cannot be mandatory.

    Правилоtopaz.rule.structures.protocols.implementation.method-restrictions

    Implementation methods use ordinary functions

    An implementation method is checked as an ordinary function against the protocol signature. Matching method generics and a matching variadic tail are admitted, and the result annotation may be omitted. Method-level export and parameter-default initializers produce TPZ5022. Conformance visibility already exposes the promised operations, and the protocol declaration already supplies omitted arguments. An implementation cannot create a second export or default contract, even by repeating the same default expression.

    The implementation binder list encloses every method. Each method binder list is a nested lexical scope. A shadowed name denotes the inner binder; it is not silently identified with the outer binder during signature matching. Generic conformance defines the same scope for receiver implementations and conditional derives.

    Причина

    Generic methods, variadic tails, and contextual results have the same function meaning inside an implementation. Visibility and defaults each already have one owner, so repeating either on a method would create competing descriptions of the same operation.

    Правилоtopaz.rule.structures.protocols.implementation.unique-conformance

    One conformance across the dependency graph

    At most one conformance may apply to a resolved protocol and normalized target type throughout the complete resolved dependency graph. Expand aliases, retain defining-module nominal identities, and rename each declaration's binders before comparing target heads. Heads overlap when some consistent substitution makes their full target types equal. Repeated variables must keep the same substitution. Different positive bound sets cannot establish disjointness, even when no current type satisfies both. Reject every overlap with TPZ5521 before module initialization, whether it is manual/manual, manual/derive, or derive/derive. A concrete implementation has no priority over a generic one. Declaration order, import order, aliases, and method bodies cannot choose a winner. Distinct heads that cannot unify remain independent. Overlap diagnostics use the target of the later manual declaration in deterministic dependency-first module and source order. A conflict involving derive points to the derived protocol head; two derives use the later clause by the same order.

    For example, Eq<Box<T>> overlaps Eq<Box<int>>. Mark<Box<int>> and Mark<Box<string>> are disjoint. Mark<Box<T>> and Mark<Box<U>> overlap even if their binders carry different positive bounds. Derive-generated conformances enter this same comparison. Normalization uses static type equality, so the rule does not add value-based or subtype-based implementation selection.

    For two conflicting manual declarations, report the target of the later declaration in deterministic dependency-first module order, using source order within a module. If a derive clause participates, report its protocol head; for two derive clauses, choose the later clause by that same order. A secondary location may identify the other declaration. This reporting order never selects an implementation.

    Причина

    Dispatch must identify one operation from its protocol and static type. Rejecting overlap makes that meaning independent of import and declaration order, and prevents later conformances from changing an earlier specialization choice. A stable primary location lets a caller fix the conflicting declaration without making import order affect which source is reported.

    Правилоtopaz.rule.structures.protocols.generic-conformance-direction

    Generic binders and conditional conformance

    An implementation places its type binders before its head, as in impl<T: Eq> Eq<Box<T>>. A receiver implementation uses the same placement, impl<T> Box<T>. Resolve the head to distinguish a protocol application from a nominal receiver; spelling, capitalization, and whitespace do not choose the meaning. Implementation binders scope over their bounds, the complete target type, and every method signature and body. Every implementation binder must occur in the target, so the selected target determines its arguments. Method binders have ordinary nested lexical scope and may shadow outer binders; matching uses resolved binder identities, never name strings. Each binder list has distinct names. A protocol method already has implicit Self in its binder scope. Bounds must have independent conformance evidence; an active obligation cannot prove itself. A generic nominal writes an explicit conditional derive binder list even when it has no bounds. Those binders scope only over that clause, correspond positionally to the nominal parameters, and may be renamed. Each derive target is the declaring nominal applied to all of those binders in declaration order. Fields and enum payloads keep the nominal declaration binders. Concrete and conditional manual and derived conformances use the same uniqueness rule.

    Write record Box<T> derives<U: Eq> Eq<Box<U>> { value: T } to rename the clause-local binder. Its positional correspondence is with the nominal parameter T; it does not rebind T inside the fields. A concrete impl Eq<Box<int>> is a concrete head, while impl<T: Eq> Eq<Box<T>> covers every target satisfying the bound. They overlap and cannot coexist. A blanket implementation such as impl<T> Local<T> is permitted in the module defining Local and excludes every overlapping Local implementation. A type alias is expanded before ownership, matching, or overlap is decided.

    Причина

    Explicit lexical binders make a generic conformance one reusable definition. Resolving types before comparing signatures prevents renaming or shadowing from capturing a different type variable. One conformance lookup for every instantiated target avoids overload or specialization priorities.

    Implement equality for a generic wrapper

    Ссылка
    example.tpzImplement equality for a generic wrapperОткрыть песочницу →
    1. record Box<T> { value: T }
    2. impl<T: Eq> Eq<Box<T>> {
    3. function equals(a: Box<T>, b: Box<T>) -> bool {
    4. Eq.equals(a.value, b.value)
    5. }
    6. }
    7. let left: Box<int> = Box { value: 3 }
    8. let right: Box<int> = Box { value: 3 }
    9. let same: bool = Eq.equals(left, right)
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Protocol calls and resolution

    Ссылка
    Правилоtopaz.rule.structures.protocols.call.target

    Protocol-qualified calls

    Resolve the protocol and method, then apply the ordinary generic-function call rules. The call type-parameter list is Self followed by the method binders in declaration order. Infer the complete list, or write it after the method name as Protocol.method<Receiver, MethodType>(arguments). Implementation binders are determined by the selected conforming type and are not extra call arguments. Parentheses around the callee preserve the same declaration signature. No separate Protocol<Type>.method call form is introduced.

    Причина

    A protocol-qualified operation is still one generic callable. One inference and explicit-specialization rule keeps ordinary functions, callbacks, and protocol calls compatible.

    Правилоtopaz.rule.structures.protocols.call.conformance

    Protocol call conformance

    Check conformance for the resolved Self type, independently of whether a value of that type occurs first, later, or only in the result. A generic body may use its declared protocol bound as conformance evidence. A concrete type without the required conformance produces TPZ5522. Dispatch uses that one conformance and does not select an implementation from the runtime value or from argument order.

    Причина

    Arguments and results may establish the same conforming type. Looking up that type and the resolved protocol identity gives the operation one behavior without requiring a dummy receiver value.

    Правилоtopaz.rule.structures.protocols.call.argument-form

    Protocol argument forms

    Protocol calls supply positional values and may spread an array into a declared variadic tail. Fixed omissions use the protocol defaults. The callee and supplied arguments are evaluated once from left to right; missing defaults follow in parameter order. Spread cannot fill an unsatisfied fixed slot. A named argument is rejected during parsing with TPZ2001, as in every other call.

    Причина

    One argument-binding and evaluation rule lets an operation move between an ordinary function and a protocol without changing its call behavior.

    Правилоtopaz.rule.structures.protocols.bound.conformance

    Protocol bounds

    A function protocol bound checks the inferred concrete type argument through conformance lookup. An unsatisfied bound produces TPZ5522.

    Причина

    A generic body may use every operation promised by its bounds. Checking conformance when binding a concrete type keeps those operations available.

    Правилоtopaz.rule.structures.protocols.conformance.visibility

    Conformance across modules

    Manual and derived conformances are available in the defining module and in modules that import the nominal type. Import aliases preserve that conformance.

    Причина

    A conformance belongs to the type and protocol identities. Importing that type must preserve its operations whether the methods are written or derived.

    Правилоtopaz.rule.structures.source.protocol-module-identity

    Conformance follows nominal origin across imports

    Resolve a conformance by the protocol declaration identity and the normalized receiver type. User protocols and nominal types retain their defining module through selected or namespace imports and aliases. Same-spelled declarations in different modules remain distinct. Manual and derived conformances in the resolved dependency graph participate in the same coherence check. Import paths, aliases, and item order do not create or select another conformance. A manual call uses the implementation from the conformance-defining module. A receiver without an applicable conformance is rejected with TPZ5522. Conformance ownership and overlap follow the implementation rules.

    Причина

    A call must keep its meaning when an import is renamed or moved. Resolve both the protocol and receiver type to their defining identities, and check one coherent set of conformances for the dependency graph. The defining module of a conformance determines its implementation, so aliases and import order cannot select a different body.

    Правилоtopaz.rule.structures.source.protocol-name-resolution

    Protocol heads respect local values and declaration identity

    A protocol declaration creates a non-value protocol binding in the same lexical and module name table as other declarations. It is private unless prefixed with export. Selected imports, selected aliases, and namespace imports resolve that binding by its defining module and declaration. Use P or ns.P in protocol bounds and conformance heads, and P.method or ns.P.method for calls. Aliases preserve identity; equal spellings in different modules remain different protocols. A same-scope name collision follows the module duplicate-binding rule. A nearer value or namespace owns an expression member access and is not reinterpreted as a protocol. Eq, Order, Show, and JSON remain predeclared protocol identities. Protocol names are not runtime values or nominal value types. A public callable may expose a user-protocol bound when that protocol is exported; a private bound is rejected with TPZ5524. Exported protocol method signatures obey the ordinary public-type visibility check. Importing a public type does not implicitly export the private protocols in its defining module. Derive eligibility is unchanged by importing a protocol name.

    Причина

    Moving a generic API into a module must preserve its protocol contract. Protocols therefore use the ordinary explicit export and import boundary. One lexical binding table prevents a spelling from silently denoting separate declarations in the same scope. Defining identities survive aliases and keep independent modules from accidentally sharing conformances. Public signatures expose public contracts; private implementation details remain private.

    A selected protocol alias preserves a public conformance

    Ссылка
    example.tpzA selected protocol alias preserves a public conformanceОткрыть песочницу →
    1. import std.io { writeLine }
    2. import contracts { Labelled as Described }
    3. import item { Item }
    4. function describe<T: Described>(value: T) -> string { Described.label(value) }
    5. writeLine(describe(Item { text: "selected" }))
    Ожидаемый выводКод завершения 0
    selected
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    contracts.tpzA selected protocol alias preserves a public conformanceОткрыть песочницу →
    1. export protocol Labelled { function label(value: Self) -> string }
    item.tpzA selected protocol alias preserves a public conformanceОткрыть песочницу →
    1. import contracts { Labelled }
    2. export record Item { text: string }
    3. impl Labelled<Item> {
    4. function label(value: Item) -> string { value.text }
    5. }
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. selected

    A namespace-qualified protocol resolves in bounds, impl heads, and calls

    Ссылка
    example.tpzA namespace-qualified protocol resolves in bounds, impl heads, and callsОткрыть песочницу →
    1. import std.io { writeLine }
    2. import contracts as api
    3. import item { Item }
    4. function describe<T: api.Labelled>(value: T) -> string { api.Labelled.label(value) }
    5. writeLine(describe(Item { text: "qualified" }))
    Ожидаемый выводКод завершения 0
    qualified
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    contracts.tpzA namespace-qualified protocol resolves in bounds, impl heads, and callsОткрыть песочницу →
    1. export protocol Labelled { function label(value: Self) -> string }
    item.tpzA namespace-qualified protocol resolves in bounds, impl heads, and callsОткрыть песочницу →
    1. import contracts as api
    2. export record Item { text: string }
    3. impl api.Labelled<Item> {
    4. function label(value: Item) -> string { value.text }
    5. }
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. qualified

    Equal protocol spellings in different modules keep different conformances

    Ссылка
    example.tpzEqual protocol spellings in different modules keep different conformancesОткрыть песочницу →
    1. import std.io { writeLine }
    2. import first { Marked as First }
    3. import second { Marked as Second }
    4. import value { Item }
    5. function printBoth<T: First + Second>(value: T) -> () {
    6. writeLine(First.mark(value))
    7. writeLine(Second.mark(value))
    8. }
    9. printBoth(Item { text: "value" })
    Ожидаемый выводКод завершения 0
    first value
    second value
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    value.tpzEqual protocol spellings in different modules keep different conformancesОткрыть песочницу →
    1. export record Item { text: string }
    first.tpzEqual protocol spellings in different modules keep different conformancesОткрыть песочницу →
    1. import value { Item }
    2. export protocol Marked { function mark(value: Self) -> string }
    3. impl Marked<Item> { function mark(value: Item) -> string { "first {value.text}" } }
    second.tpzEqual protocol spellings in different modules keep different conformancesОткрыть песочницу →
    1. import value { Item }
    2. export protocol Marked { function mark(value: Self) -> string }
    3. impl Marked<Item> { function mark(value: Item) -> string { "second {value.text}" } }
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. first value
    2. second value

    An exported function may expose an exported user protocol bound

    Ссылка
    example.tpzAn exported function may expose an exported user protocol boundОткрыть песочницу →
    1. export protocol Labelled { function label(value: Self) -> string }
    2. export function describe<T: Labelled>(value: T) -> string { Labelled.label(value) }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Reject a public callable that exposes a private protocol bound

    Ссылка
    example.tpzReject a public callable that exposes a private protocol boundОткрыть песочницу →
    1. protocol Hidden { function label(value: Self) -> string }
    2. export function describe<T: Hidden>(value: T) -> string { Hidden.label(value) }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5524 →

      protocol-private-public-bound at example.tpz:2:29

    A private protocol is not selected through import

    Ссылка
    example.tpzA private protocol is not selected through importОткрыть песочницу →
    1. import contracts { Hidden }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    contracts.tpzA private protocol is not selected through importОткрыть песочницу →
    1. protocol Hidden { function label(value: Self) -> string }
    2. export let marker = 0
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения resolve. Ненулевой код завершения.

    • TPZ3009 →

      protocol-name-not-exported at example.tpz:1:20

    A protocol and a value cannot bind the same module-level name

    Ссылка
    example.tpzA protocol and a value cannot bind the same module-level nameОткрыть песочницу →
    1. protocol Labelled { function label(value: Self) -> string }
    2. let Labelled = 0
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения resolve. Ненулевой код завершения.

    • TPZ3008 →

      protocol-binding-name-collision at example.tpz:2:5

    An exported protocol cannot expose a private nominal parameter type

    Ссылка
    example.tpzAn exported protocol cannot expose a private nominal parameter typeОткрыть песочницу →
    1. record Hidden { n: int }
    2. export protocol Render { function render(value: Self, input: Hidden) -> string }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения resolve. Ненулевой код завершения.

    • TPZ3014 →

      modules-public-private-nominal at example.tpz:2:62

    An exported protocol signature may use an exported nominal type

    Ссылка
    example.tpzAn exported protocol signature may use an exported nominal typeОткрыть песочницу →
    1. export record Input { n: int }
    2. export protocol Render { function render(value: Self, input: Input) -> string }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Namespace qualification whitespace cannot repeat one protocol bound

    Ссылка
    example.tpzNamespace qualification whitespace cannot repeat one protocol boundОткрыть песочницу →
    1. import contracts as api
    2. function describe<T: api.Labelled + api . Labelled>(value: T) -> string { api.Labelled.label(value) }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    contracts.tpzNamespace qualification whitespace cannot repeat one protocol boundОткрыть песочницу →
    1. export protocol Labelled { function label(value: Self) -> string }
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5523 →

      protocol-repeated-resolved-bound at example.tpz:2:37

    Derived conformance

    Ссылка

    For declaration grammar, see Records, enums and newtypes.

    Правилоtopaz.rule.structures.protocols.derive.protocols

    Derivable protocols

    For a nongeneric record, enum, or newtype, derives requests Eq, Order, Show, or JSON conformance. Another protocol name produces TPZ5530.

    Причина

    Generated operations need a defined derivation for each field, variant payload, or newtype base. The built-in protocols supply those rules for all three nominal declaration forms.

    Правилоtopaz.rule.structures.protocols.derive.show

    Show derivation

    Show derivation for a nongeneric record, enum, or newtype requires no member capability test. A newtype is displayed by its type name followed by its rendered base value in parentheses.

    Причина

    Derived Show uses the shared value renderer, which handles every runtime value, including opaque values and functions. Its fields need no separate Show conformance.

    Правилоtopaz.rule.structures.protocols.derive.field-capabilities

    Derivation field and payload requirements

    Eq, Order, and JSON derivation check every record field, enum payload, or newtype base for equality, total ordering, or both JSON conversion operations. Each operation uses the capability domain described below. JSON decoding follows the declared normalization rules, including Option null conversion. A member that lacks the required capability produces TPZ5530.

    Причина

    A generated operation visits the constituent fields or payloads. Each constituent must support the corresponding equality, ordering, or JSON conversion operation.

    Правилоtopaz.rule.structures.protocols.derive.json-manual

    JSON conformance

    JSON is an ordinary conformance with encode(value: Self) -> Result<JSONValue, string> and decode(value: JSONValue) -> Result<Self, string>. An implementation supplies both methods. An empty marker produces the missing-method error TPZ5022. The ordinary protocol call rules infer Self or select it through the first explicit call type argument, as in JSON.decode<Token>(tree). std.json.stringify calls encode and then the canonical JSONValue writer. std.json.parseAs<T> parses the text and calls the same decode implementation selected by JSON.decode<T>. A codec returns an Err result for invalid input or a value it cannot encode. These failures do not become checker diagnostics. The manual decoder owns the accepted JSONValue shape. Derived record decoders ignore unknown object fields and use declared field defaults when a field is missing. A missing required field, wrong kind, unknown enum tag, or wrong payload arity returns an Err result. Malformed text fails before the decoder is called. JSON promises both conversion operations, with the representation and normalization defined for the type. Conversion may normalize distinct source values to the same decoded value. Existing Option conversion maps None() to null and Some(v) to the representation of v, so Some(None()) and Some(()) normalize to None() when decoded through an enclosing Option. Decode a JSONValue with JSON.decode<T>(tree). The receiver member tree.decode<T>() is removed and produces the ordinary missing-member diagnostic TPZ5006. Parsing text and writing text remain distinct operations through parseAs and stringify.

    Причина

    A public codec should customize the same operation that library callers use. Supplying encode and decode through ordinary protocol methods lets a nominal type define its external representation without a second ad hoc serialization API. JSONValue separates typed conversion from parsing and canonical text output. The Result channel reports data failures in the same way for manual and derived implementations. Existing record default and Option normalization rules remain explicit conversion semantics. Decoding an existing tree has one public spelling, the ordinary protocol-qualified call. A receiver alias would repeat the same operation with identical input and output.

    Правилоtopaz.rule.structures.protocols.builtin.signatures

    Built-in protocol signatures

    The built-in method signatures are Show.show(value: Self) -> string, Eq.equals(a: Self, b: Self) -> bool, Order.compare(a: Self, b: Self) -> int, JSON.encode(value: Self) -> Result<JSONValue, string>, and JSON.decode(value: JSONValue) -> Result<Self, string>. JSONValue is the parsed JSON tree type exported by std.json. JSON decode uses the ordinary protocol rule for selecting Self when there is no conforming input value.

    Причина

    Shared signatures let user types participate in the same display, equality, and ordering operations. Callers do not need separate APIs for each type.

    Правилоtopaz.rule.structures.source.derive-nominal-recursion

    Nested and recursive derivation requirements

    Deriving Eq, Order, or JSON composes the same operation on every record field, enum payload, or newtype base. A nested nominal uses its applicable manual or derived conformance after type arguments are substituted in its defining module. A manual method replaces structural inspection of that nominal; an outer derive must not bypass it or reject it because of private representation fields. A nested nominal with no required conformance produces TPZ5530. Built-in component families use the corresponding operation domain below.

    Declared recursive and mutually recursive conformances may refer to one another. A recursive edge closes a declared conformance reference; it does not excuse a missing component capability elsewhere in the cycle. Establish each conditional instance using independent generic bound evidence before linking its recursive descriptors. An active generic bound cannot prove itself; a back-edge between already applicable declared derives is a descriptor reference, not evidence for that bound. A descriptor is identified by defining module, nominal declaration, and normalized type arguments. Keep references and captured substitutions and instantiate them as values are traversed, rather than eagerly expanding a schema tree. Imported aliases keep the same descriptor identity. Conditional generic instances follow the ordinary binder and coherence rules.

    A derived JSON decoder follows the finite input tree. Each recursive aggregate step consumes a child JSON value; a descriptor loop that revisits the same input without structural progress returns Err. JSON starts at depth zero, permits depths through 128, and increments depth when descending to a record field, array element, map value, or enum payload. Descriptor references, Option wrapping, and newtype wrapping do not add a level. Data values follow value semantics. A depth above 128 returns an Err string beginning JSON_LIMIT:. The same traversal context covers nested derived dispatch. Descriptor expansion does not reset it. Manual method bodies retain ordinary function evaluation and resource behavior.

    Derived equality and ordering use the same nested conformance as direct protocol calls. A declared nominal Eq or Order implementation also supplies the corresponding comparison operators, so moving a comparison inside a wrapper does not change its meaning. A structural comparison that exhausts its budget raises the existing TPZ5007 guard. Show retains its total debug rendering operation and does not introduce an Eq, Order, or JSON member requirement.

    Причина

    A nominal conformance is the type author’s chosen operation, so composition calls it. Recursive declarations describe finite data trees under value semantics. Data values cannot contain cycles. Lazy descriptor references and bounded traversal support recursive declarations and deep values.

    Правилоtopaz.rule.structures.source.derive-capability-domains

    Field capability domains for derivation

    Derivation follows the operation it generates. Eq asks whether two values are equal. Order supplies a total comparison. JSON supplies conversion to and from a JSON tree under the type's documented representation. These are different obligations, so admission is determined by the operation rather than a common whitelist. A nested nominal always uses the conformance described above. This table defines the listed component families; it does not assign capabilities to other built-ins. Duration capabilities follow its operations rule.

    ComponentEqOrderJSON
    int, string, boolValue equalityNumeric, Unicode scalar, or false-before-true orderJSON number, string, or boolean
    unit and nullEquality within the singleton typeZero within the same singleton typeJSON null, recovered through the requested target type
    floatIEEE numerical equalityNo total Order because NaN has no place in the existing numerical relationFinite numbers convert; NaN and infinities return Err
    ArraySame length and elementwise equalityLexicographic elements; a prefix precedes its extensionJSON array with recursive conversion
    OptionSame constructor and payload equalityNone() precedes Some(value). Compare present payloadsNone() encodes as null. Some(value) unwraps its payload. Null payloads normalize on decoding
    ResultSame constructor and payload equalityErr before Ok; compare payloads within the same constructorThe ordinary enum object with tag Ok or Err and one values entry
    MapSame lookup key identities and equal values, independent of insertion orderRequires an application-selected orderingString keys form a JSON object; other key types need an explicit schema
    SetSame membership key identities, independent of insertion orderRequires an application-selected orderingRequires an explicit sequence representation and duplicate policy
    Structural recordSame field set and fieldwise equalityCompare fields in Unicode scalar order of field namesString field names form a JSON object
    UnionCompare active member identities, then values within a memberAdmitted when every member widens to the same ordered scalar domainUntagged overlapping representations need an explicit nominal schema

    Map and Set equality reuse the key identity already used by lookup and membership. A custom Eq method does not replace stored-key equality. Map values use their Eq operation, including a manual nominal implementation. Insertion order does not affect either equality result. Functions and resources have no data-value equality, and regex denotation has no general equality operation. JSONValue and TOMLValue preserve representation information and require decoding or an explicit projection into the intended equality domain. Templates, ranges, mutable ByteBuffer values, and namespaces likewise have no automatic Eq conformance. Bytes compare bytes; Path and URL compare their canonical representations; Date, BigInt, and Decimal compare their values; Match and RoundingMode retain their declared value equality. IEEE equality is not an equivalence relation for NaN-containing values: NaN differs from itself and positive and negative zero compare equal. Eq does not promise otherwise.

    For Order, Bytes compare bytewise; Path and URL compare canonical strings; Date compares calendar days; BigInt and Decimal compare numbers. A record uses sorted field names, including a nominal record, so rearranging declarations cannot change priority. A derived enum compares variant names in Unicode scalar order and then positional payloads. A newtype compares its base. Each component must itself have Order. Map and Set describe membership rather than a selected key order; a heterogeneous union has no declared cross-type priority. A nominal manual implementation can state those application-specific choices. Float keeps its ordinary IEEE relational predicates, which may all be false for NaN, and therefore does not satisfy total Order. Opaque families without a declared total order do not gain one through derivation.

    JSON uses the existing record object, enum tag/values object, and transparent newtype representations. Result uses the enum representation rather than treating an Err payload as codec failure. Option converts through null and its payload values. Some(None()) and Some(()) can decode as None(). This normalization can map distinct source values to the same decoded value. JSONValue conversion preserves its tree, including stored number lexemes. Semantic scalar types such as Bytes, Path, URL, Date, BigInt, Decimal, Match, and RoundingMode need an explicitly chosen external schema through a nominal manual JSON implementation. Conversion does not silently pick a binary encoding, path base, unit, precision loss, or tag convention. Functions, resources, and templates cannot be reconstructed as data values. Derived conversion failure is TPZ5530 when a component type has no JSON capability. Malformed data and value-level encoding failures return an Err result during conversion.

    Finite float encoding chooses the shortest decimal significand that recovers the identical binary64 value under nearest, ties-to-even decoding. If shortest candidates differ, choose the decimal closest to the exact binary value, then the candidate with an even final significand digit. Render fixed notation when the normalized decimal exponent is at least -6 and below 21; otherwise use lowercase e, with no plus sign or redundant exponent zeroes. Omit redundant fractional zeroes. Positive zero is 0 and negative zero is -0. A nonfinite input returns Err without substituting null or a string. Decoding accepts any JSON number, including integer lexemes, rounds once to binary64 with nearest, ties-to-even, preserves a negative zero sign, and rejects overflow to a nonfinite result. Underflow rounds to a finite subnormal or signed zero. The shortest-number rule applies when encoding a float; parsing and re-serializing an existing JSONValue preserves its accepted number lexeme, and numberText/asInt retain their existing semantics. Recursive conversion follows the depth rule above and value semantics. Show remains the total debug-render operation and has no member capability gate.

    Duration has Eq and Order under its operations rule. Duration has no JSON capability in 6.0.

    Причина

    Equal membership, lexicographic sequence order, total comparison, and JSON conversion answer different questions. Their requirements follow those questions. Map and Set equality should agree with lookup and membership instead of requiring an arbitrary insertion order. A total Order cannot inherit IEEE NaN comparison. A finite float can use the JSON number domain while the existing Result channel handles nonfinite values. JSON schemas that require an application choice stay explicit, and declaration layout does not choose a comparison priority.

    Derive equality under an element bound

    Ссылка
    example.tpzDerive equality under an element boundОткрыть песочницу →
    1. record Box<T> derives<T: Eq> Eq<Box<T>> { value: T }
    2. let left: Box<int> = Box { value: 3 }
    3. let right: Box<int> = Box { value: 3 }
    4. let same: bool = Eq.equals(left, right)
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Derive the existing protocols for a newtype

    Ссылка
    example.tpzDerive the existing protocols for a newtypeОткрыть песочницу →
    1. newtype Item derives Eq, Order, Show, JSON = int
    2. function jsonIdentity<T: JSON>(value: T) -> T { value }
    3. let value = Item(7)
    4. let same: bool = Eq.equals(value, value)
    5. let order: int = Order.compare(value, Item(8))
    6. let shown: string = Show.show(value)
    7. let retained: Item = jsonIdentity(value)
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Call derived Eq and Show on a newtype

    Ссылка
    example.tpzCall derived Eq and Show on a newtype
    1. import std.io { writeLine }
    2. newtype Item derives Eq, Show = int
    3. let value = Item(7)
    4. writeLine("{Eq.equals(value, Item(7))}")
    5. writeLine("{Eq.equals(value, Item(8))}")
    6. writeLine(Show.show(value))
    Ожидаемый выводКод завершения 0
    true
    false
    Item(7)
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. true
    2. false
    3. Item(7)

    Use the conditional derive binder on a newtype

    Ссылка
    example.tpzUse the conditional derive binder on a newtypeОткрыть песочницу →
    1. newtype Box<T> derives<T: Eq> Eq<Box<T>> = T
    2. let left: Box<int> = Box(3)
    3. let right: Box<int> = Box(3)
    4. let same: bool = Eq.equals(left, right)
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Require an explicit newtype conformance

    Ссылка
    example.tpzRequire an explicit newtype conformanceОткрыть песочницу →
    1. newtype Item = int
    2. let value = Item(7)
    3. let same = Eq.equals(value, value)
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5522 →

      structures-no-visible-eq-conformance at example.tpz:3:22

    A manual JSON implementation supplies both conversions

    Ссылка
    example.tpzA manual JSON implementation supplies both conversionsОткрыть песочницу →
    1. import std.json { JSONValue }
    2. record Token { text: string }
    3. impl JSON<Token> {
    4. function encode(value: Token) -> Result<JSONValue, string> {
    5. JSON.encode(value.text)
    6. }
    7. function decode(value: JSONValue) -> Result<Token, string> {
    8. match (value.asString()) {
    9. case Some(text) => Ok(Token { text: text })
    10. case None() => Err("expected token string")
    11. }
    12. }
    13. }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Text and tree conversion use the same manual JSON implementation

    Ссылка
    example.tpzText and tree conversion use the same manual JSON implementation
    1. import std.io { writeLine }
    2. import std.json { JSONValue, parse, parseAs, stringify }
    3. record Token { text: string }
    4. impl JSON<Token> {
    5. function encode(value: Token) -> Result<JSONValue, string> {
    6. JSON.encode(value.text)
    7. }
    8. function decode(value: JSONValue) -> Result<Token, string> {
    9. match (value.asString()) {
    10. case Some(text) => Ok(Token { text: text })
    11. case None() => Err("expected token string")
    12. }
    13. }
    14. }
    15. writeLine(match (stringify(Token { text: "paper" })) {
    16. case Ok(text) => text
    17. case Err(message) => message
    18. })
    19. writeLine(match (parseAs<Token>("\"paper\"")) {
    20. case Ok(value) => value.text
    21. case Err(message) => message
    22. })
    23. writeLine(match (parseAs<Token>("17")) {
    24. case Ok(value) => value.text
    25. case Err(message) => message
    26. })
    27. writeLine(match (parse("\"ink\"")) {
    28. case Ok(tree) => match (JSON.decode<Token>(tree)) {
    29. case Ok(value) => value.text
    30. case Err(message) => message
    31. }
    32. case Err(_) => "parse failed"
    33. })
    Ожидаемый выводКод завершения 0
    "paper"
    paper
    expected token string
    ink
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. "paper"
    2. paper
    3. expected token string
    4. ink

    An empty JSON marker omits the required conversion methods

    Ссылка
    example.tpzAn empty JSON marker omits the required conversion methodsОткрыть песочницу →
    1. record Token { text: string }
    2. impl JSON<Token> {}
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    Derived JSON keeps record defaults and ignores unknown object fields

    Ссылка
    example.tpzDerived JSON keeps record defaults and ignores unknown object fields
    1. import std.io { writeLine }
    2. import std.json { parseAs, stringify }
    3. record Item derives JSON { name: string, count: int = 7 }
    4. let text = match (stringify({ name: "ink", extra: true })) {
    5. case Ok(value) => value
    6. case Err(message) => message
    7. }
    8. writeLine(match (parseAs<Item>(text)) {
    9. case Ok(value) => "{value.name}:{value.count}"
    10. case Err(message) => message
    11. })
    12. writeLine(match (parseAs<Item>("17")) {
    13. case Ok(_) => "unexpected value"
    14. case Err(_) => "wrong shape"
    15. })
    16. writeLine(match (parseAs<Item>("[")) {
    17. case Ok(_) => "unexpected value"
    18. case Err(_) => "malformed text"
    19. })
    Ожидаемый выводКод завершения 0
    ink:7
    wrong shape
    malformed text
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. ink:7
    2. wrong shape
    3. malformed text

    JSONValue decoding uses the ordinary protocol call

    Ссылка
    example.tpzJSONValue decoding uses the ordinary protocol callОткрыть песочницу →
    1. import std.json { JSONValue }
    2. function read(tree: JSONValue) -> Result<int, string> {
    3. tree.decode<int>()
    4. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    Decode a JSONValue with one protocol-qualified form

    Ссылка
    example.tpzDecode a JSONValue with one protocol-qualified formОткрыть песочницу →
    1. import std.json { JSONValue }
    2. function read(tree: JSONValue) -> Result<int, string> {
    3. JSON.decode<int>(tree)
    4. }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Derived equality and operators use the inner manual equality

    Ссылка
    example.tpzDerived equality and operators use the inner manual equality
    1. import std.io { writeLine }
    2. record Token { key: int, noise: int }
    3. impl Eq<Token> {
    4. function equals(a: Token, b: Token) -> bool { a.key == b.key }
    5. }
    6. record Box derives Eq { item: Token }
    7. let a = Box { item: Token { key: 1, noise: 10 } }
    8. let b = Box { item: Token { key: 1, noise: 20 } }
    9. let c = Box { item: Token { key: 2, noise: 10 } }
    10. writeLine("{Eq.equals(a, b)}")
    11. writeLine("{a == b}")
    12. writeLine("{Eq.equals(a, c)}")
    13. writeLine("{a != c}")
    Ожидаемый выводКод завершения 0
    true
    true
    false
    true
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. true
    2. true
    3. false
    4. true

    A manual equality hides an opaque field from outer operators

    Ссылка
    example.tpzA manual equality hides an opaque field from outer operators
    1. import std.io { writeLine }
    2. record Callback { key: int, run: () -> int }
    3. impl Eq<Callback> {
    4. function equals(a: Callback, b: Callback) -> bool { a.key == b.key }
    5. }
    6. record Box derives Eq { item: Callback }
    7. let a = Box { item: Callback { key: 1, run: () => 7 } }
    8. let b = Box { item: Callback { key: 1, run: () => 9 } }
    9. writeLine("{a == b}")
    10. writeLine("{Eq.equals(a, b)}")
    Ожидаемый выводКод завершения 0
    true
    true
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. true
    2. true

    Derived ordering and operators use the inner manual ordering

    Ссылка
    example.tpzDerived ordering and operators use the inner manual ordering
    1. import std.io { writeLine }
    2. record Rank { score: int }
    3. impl Order<Rank> {
    4. function compare(a: Rank, b: Rank) -> int {
    5. if (a.score > b.score) { -1 } else if (a.score < b.score) { 1 } else { 0 }
    6. }
    7. }
    8. record Box derives Order { item: Rank }
    9. let a = Box { item: Rank { score: 9 } }
    10. let b = Box { item: Rank { score: 3 } }
    11. writeLine("{Order.compare(a, b)}")
    12. writeLine("{a < b}")
    13. writeLine("{Order.compare(b, a)}")
    14. writeLine("{b > a}")
    Ожидаемый выводКод завершения 0
    -1
    true
    1
    true
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. -1
    2. true
    3. 1
    4. true

    Derived JSON uses the nested manual codec in both directions

    Ссылка
    example.tpzDerived JSON uses the nested manual codec in both directions
    1. import std.io { writeLine }
    2. import std.json { JSONValue, parseAs, stringify }
    3. record Token { text: string }
    4. impl JSON<Token> {
    5. function encode(value: Token) -> Result<JSONValue, string> {
    6. JSON.encode(value.text)
    7. }
    8. function decode(value: JSONValue) -> Result<Token, string> {
    9. match (value.asString()) {
    10. case Some(text) => Ok(Token { text: text })
    11. case None() => Err("expected token string")
    12. }
    13. }
    14. }
    15. record Envelope derives JSON { token: Token }
    16. let text = match (stringify(Envelope { token: Token { text: "paper" } })) {
    17. case Ok(value) => value
    18. case Err(message) => message
    19. }
    20. writeLine(text)
    21. writeLine(match (parseAs<Envelope>(text)) {
    22. case Ok(value) => value.token.text
    23. case Err(message) => message
    24. })
    Ожидаемый выводКод завершения 0
    {"token":"paper"}
    paper
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. {"token":"paper"}
    2. paper

    A finite recursive enum value encodes and decodes

    Ссылка
    example.tpzA finite recursive enum value encodes and decodes
    1. import std.io { writeLine }
    2. import std.json { parseAs, stringify }
    3. enum Chain derives Eq, JSON { End, Next(int, Chain) }
    4. let original = Chain.Next(7, Chain.End())
    5. let text = match (stringify(original)) {
    6. case Ok(value) => value
    7. case Err(message) => message
    8. }
    9. writeLine(text)
    10. writeLine(match (parseAs<Chain>(text)) {
    11. case Ok(value) => "{Eq.equals(value, original)}"
    12. case Err(message) => message
    13. })
    Ожидаемый выводКод завершения 0
    {"tag":"Next","values":[7,{"tag":"End"}]}
    true
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. {"tag":"Next","values":[7,{"tag":"End"}]}
    2. true

    Mutually recursive declarations share conformance references

    Ссылка
    example.tpzMutually recursive declarations share conformance referencesОткрыть песочницу →
    1. record Folder derives Eq, JSON { entries: Array<Entry> }
    2. enum Entry derives Eq, JSON { File(string), Directory(Folder) }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Inserted values keep recursive JSON finite

    Ссылка
    example.tpzInserted values keep recursive JSON finite
    1. import std.io { writeLine }
    2. import std.json { stringify }
    3. record Node derives JSON { children: Array<Node> }
    4. let mut children: Array<Node> = []
    5. let root = Node { children: children }
    6. children.push(root)
    7. writeLine("{root.children.length}:{children.length}")
    8. writeLine(match (stringify(root)) {
    9. case Ok(value) => "Ok {value}"
    10. case Err(_) => "unexpected error"
    11. })
    Ожидаемый выводКод завершения 0
    0:1
    Ok {"children":[]}
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. 0:1
    2. Ok {"children":[]}

    The record retains its empty children value after children.push(root). Insertion follows value semantics and cannot create a cycle.

    Inserted values keep recursive comparison finite

    Ссылка
    example.tpzInserted values keep recursive comparison finite
    1. import std.io { writeLine }
    2. record Node derives Eq { children: Array<Node> }
    3. let mut children: Array<Node> = []
    4. let root = Node { children: children }
    5. let peer = Node { children: children }
    6. children.push(root)
    7. writeLine("{Eq.equals(root, peer)}:{root.children.length}:{children.length}")
    Ожидаемый выводКод завершения 0
    true:0:1
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. true:0:1

    The record retains its empty children value after children.push(root). Insertion follows value semantics and cannot create a cycle.

    Outer derivation does not invent an inner nominal conformance

    Ссылка
    example.tpzOuter derivation does not invent an inner nominal conformanceОткрыть песочницу →
    1. record Inner { value: int }
    2. record Outer derives Eq { item: Inner }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      structures-derive-eq-field at example.tpz:2:22

    Nested dispatch preserves the imported nominal identity

    Ссылка
    example.tpzNested dispatch preserves the imported nominal identityОткрыть песочницу →
    1. import std.io { writeLine }
    2. import tokens { Token as Ink }
    3. record Box derives Eq { value: Ink }
    4. let a = Box { value: Ink { key: 4, label: "first" } }
    5. let b = Box { value: Ink { key: 4, label: "second" } }
    6. writeLine("{Eq.equals(a, b)}")
    Ожидаемый выводКод завершения 0
    true
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    tokens.tpzNested dispatch preserves the imported nominal identityОткрыть песочницу →
    1. export record Token { key: int, label: string }
    2. impl Eq<Token> {
    3. function equals(a: Token, b: Token) -> bool { a.key == b.key }
    4. }
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. true

    Map and Set equality follows membership while Map values use Eq

    Ссылка
    example.tpzMap and Set equality follows membership while Map values use Eq
    1. import std.io { writeLine }
    2. record Token { key: int, label: string }
    3. impl Eq<Token> {
    4. function equals(a: Token, b: Token) -> bool { a.key == b.key }
    5. }
    6. record Index derives Eq { values: Map<string, Token>, keys: Set<int> }
    7. let a = Index {
    8. values: map { "a": Token { key: 1, label: "first" }, "b": Token { key: 2, label: "second" } },
    9. keys: set { 1, 2 },
    10. }
    11. let b = Index {
    12. values: map { "b": Token { key: 2, label: "changed" }, "a": Token { key: 1, label: "changed" } },
    13. keys: set { 2, 1 },
    14. }
    15. let c = Index {
    16. values: map { "a": Token { key: 9, label: "first" }, "b": Token { key: 2, label: "second" } },
    17. keys: set { 1, 2 },
    18. }
    19. writeLine("{Eq.equals(a, b)}")
    20. writeLine("{a == b}")
    21. writeLine("{Eq.equals(a, c)}")
    Ожидаемый выводКод завершения 0
    true
    true
    false
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. true
    2. true
    3. false

    Boolean, singleton, sequence, sum, and structural record orders compose

    Ссылка
    example.tpzBoolean, singleton, sequence, sum, and structural record orders compose
    1. import std.io { writeLine }
    2. record Flag derives Order { value: bool }
    3. record UnitBox derives Order { value: () }
    4. record NullBox derives Order { value: null }
    5. record Sequence derives Order { value: Array<int> }
    6. record Optional derives Order { value: Option<int> }
    7. record Outcome derives Order { value: Result<int, int> }
    8. record Fields derives Order { value: { z: int, a: int } }
    9. writeLine("{Order.compare(Flag { value: false }, Flag { value: true })}")
    10. writeLine("{Order.compare(UnitBox { value: () }, UnitBox { value: () })}")
    11. writeLine("{Order.compare(NullBox { value: null }, NullBox { value: null })}")
    12. writeLine("{Order.compare(Sequence { value: [1, 2] }, Sequence { value: [1, 3] })}")
    13. writeLine("{Order.compare(Sequence { value: [1] }, Sequence { value: [1, 0] })}")
    14. writeLine("{Order.compare(Optional { value: None() }, Optional { value: Some(0) })}")
    15. writeLine("{Order.compare(Outcome { value: Err(7) }, Outcome { value: Ok(0) })}")
    16. writeLine("{Order.compare(Fields { value: { z: 0, a: 2 } }, Fields { value: { z: 100, a: 1 } })}")
    Ожидаемый выводКод завершения 0
    -1
    0
    0
    -1
    -1
    -1
    -1
    1
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. -1
    2. 0
    3. 0
    4. -1
    5. -1
    6. -1
    7. -1
    8. 1

    Reordering record fields or enum declarations does not change derived order

    Ссылка
    example.tpzReordering record fields or enum declarations does not change derived order
    1. import std.io { writeLine }
    2. record First derives Order { z: int, a: int }
    3. record Second derives Order { a: int, z: int }
    4. enum Forward derives Order { Zed, Alpha }
    5. enum Reordered derives Order { Alpha, Zed }
    6. writeLine("{Order.compare(First { z: 0, a: 2 }, First { z: 100, a: 1 })}")
    7. writeLine("{Order.compare(Second { z: 0, a: 2 }, Second { z: 100, a: 1 })}")
    8. writeLine("{Order.compare(Forward.Alpha(), Forward.Zed())}")
    9. writeLine("{Order.compare(Reordered.Alpha(), Reordered.Zed())}")
    Ожидаемый выводКод завершения 0
    1
    1
    -1
    -1
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. 1
    2. 1
    3. -1
    4. -1

    A union within one ordered scalar domain keeps that order

    Ссылка
    example.tpzA union within one ordered scalar domain keeps that order
    1. import std.io { writeLine }
    2. record Choice derives Order { value: 1 | 2 }
    3. writeLine("{Order.compare(Choice { value: 1 }, Choice { value: 2 })}")
    Ожидаемый выводКод завершения 0
    -1
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. -1

    Map membership has no implicit total ordering

    Ссылка
    example.tpzMap membership has no implicit total orderingОткрыть песочницу →
    1. record Lookup derives Order { values: Map<string, int> }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      structures-derive-order-field at example.tpz:1:23

    Set membership has no implicit total ordering

    Ссылка
    example.tpzSet membership has no implicit total orderingОткрыть песочницу →
    1. record Membership derives Order { values: Set<int> }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      structures-derive-order-field at example.tpz:1:27

    Different ordered scalar domains do not acquire a cross-type order

    Ссылка
    example.tpzDifferent ordered scalar domains do not acquire a cross-type orderОткрыть песочницу →
    1. record Mixed derives Order { value: int | string }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      structures-derive-order-field at example.tpz:1:22

    JSON object keys require strings without an implicit key conversion

    Ссылка
    example.tpzJSON object keys require strings without an implicit key conversionОткрыть песочницу →
    1. record NumericKeys derives JSON { values: Map<int, string> }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      structures-derive-json-field at example.tpz:1:28

    A Set needs an explicitly chosen JSON representation

    Ссылка
    example.tpzA Set needs an explicitly chosen JSON representationОткрыть песочницу →
    1. record Membership derives JSON { values: Set<int> }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      structures-derive-json-field at example.tpz:1:27

    Eq uses IEEE float equality and does not claim NaN reflexivity

    Ссылка
    example.tpzEq uses IEEE float equality and does not claim NaN reflexivity
    1. import std.io { writeLine }
    2. record Reading derives Eq { value: float }
    3. let sample = Reading { value: 0.0 / 0.0 }
    4. writeLine("{Eq.equals(sample, sample)}")
    5. writeLine("{sample == sample}")
    Ожидаемый выводКод завершения 0
    false
    false
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. false
    2. false

    Finite floats have one JSON number conversion and preserve negative zero

    Ссылка
    example.tpzFinite floats have one JSON number conversion and preserve negative zero
    1. import std.io { writeLine }
    2. import std.json { parseAs, stringify }
    3. record Reading derives JSON { value: float }
    4. writeLine(match (stringify(Reading { value: 1.5 })) {
    5. case Ok(text) => text
    6. case Err(message) => message
    7. })
    8. writeLine(match (stringify(-0.0)) {
    9. case Ok(text) => text
    10. case Err(message) => message
    11. })
    12. writeLine(match (stringify(1000.0)) {
    13. case Ok(text) => text
    14. case Err(message) => message
    15. })
    16. writeLine(match (parseAs<float>("-0")) {
    17. case Ok(value) => "{(1.0 / value) < 0.0}"
    18. case Err(message) => message
    19. })
    20. writeLine(match (parseAs<float>("1")) {
    21. case Ok(value) => "{value == 1.0}"
    22. case Err(message) => message
    23. })
    24. writeLine(match (stringify(0.0 / 0.0)) {
    25. case Ok(_) => "unexpected value"
    26. case Err(_) => "nonfinite rejected"
    27. })
    28. writeLine(match (parseAs<float>("1e9999")) {
    29. case Ok(_) => "unexpected value"
    30. case Err(_) => "overflow rejected"
    31. })
    Ожидаемый выводКод завершения 0
    {"value":1.5}
    -0
    1000
    true
    true
    nonfinite rejected
    overflow rejected
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. {"value":1.5}
    2. -0
    3. 1000
    4. true
    5. true
    6. nonfinite rejected
    7. overflow rejected

    Option JSON conversion explicitly normalizes null payloads

    Ссылка
    example.tpzOption JSON conversion explicitly normalizes null payloads
    1. import std.io { writeLine }
    2. import std.json { parseAs, stringify }
    3. let original: Option<Option<int>> = Some(None())
    4. writeLine(match (stringify(original)) {
    5. case Ok(text) => text
    6. case Err(message) => message
    7. })
    8. writeLine(match (parseAs<Option<Option<int>>>("null")) {
    9. case Ok(value) => match (value) {
    10. case None() => "none"
    11. case Some(_) => "some"
    12. }
    13. case Err(message) => message
    14. })
    Ожидаемый выводКод завершения 0
    null
    none
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. null
    2. none

    Result data uses the same tagged representation as enum data

    Ссылка
    example.tpzResult data uses the same tagged representation as enum data
    1. import std.io { writeLine }
    2. import std.json { parseAs, stringify }
    3. record Outcome derives JSON { value: Result<int, string> }
    4. let value = Outcome { value: Err("paper") }
    5. let text = match (stringify(value)) {
    6. case Ok(encoded) => encoded
    7. case Err(message) => message
    8. }
    9. writeLine(text)
    10. writeLine(match (parseAs<Outcome>(text)) {
    11. case Ok(decoded) => match (decoded.value) {
    12. case Ok(number) => "{number}"
    13. case Err(message) => message
    14. }
    15. case Err(message) => message
    16. })
    Ожидаемый выводКод завершения 0
    {"value":{"tag":"Err","values":["paper"]}}
    paper
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. {"value":{"tag":"Err","values":["paper"]}}
    2. paper

    Receiver methods and self

    Ссылка
    Правилоtopaz.rule.structures.protocols.receiver.parameter

    Receiver self parameter

    A receiver method starts with bare self, with no annotation, default, or variadic marker. Its type is the implementation target, and a missing or differently written receiver produces TPZ5022.

    Причина

    The implementation target already determines the receiver type. A bare self avoids repeating that type in every method and gives receiver binding one form.

    Правилоtopaz.rule.structures.protocols.receiver.unique-name

    Unique receiver method names

    Repeating a receiver method name for the same type produces TPZ5008.

    Причина

    Member lookup needs one method for a given type and name. Duplicate definitions would make a call depend on declaration order.

    Правилоtopaz.rule.structures.protocols.receiver.member-collision

    Receiver member collisions

    A receiver method name that collides with a record field or reserved built-in member produces TPZ5022.

    Причина

    Fields, built-in members, and receiver methods share member access syntax. Distinct names prevent the same access from denoting different operations.

    Правилоtopaz.rule.structures.protocols.receiver.export

    Exporting receiver methods

    export may precede an individual receiver method declaration.

    Причина

    Exporting individual methods lets a type expose useful operations while keeping helpers private. It uses the same declaration prefix as other module exports.

    Using a resource

    Ссылка

    Scope cleanup runs on normal completion and structured exits. The File resource contract defines repeated close and host close failures. Ordinary runtime faults follow the fault cleanup rule.

    Правилоtopaz.rule.structures.protocols.using.file-type

    File resource bindings

    using name = (expression) { ... } checks the resource expression against File and gives its block binding type File.

    Причина

    The cleanup path invokes the File close operation. Requiring a File ensures that this operation is defined for the acquired resource.

    Правилоtopaz.rule.structures.protocols.using.immutable-binding

    Immutable resource bindings

    A using resource binding is immutable.

    Причина

    Cleanup is registered for the acquired resource. Preventing reassignment keeps the visible binding tied to the resource that will be closed.

    Правилоtopaz.rule.structures.source.using-cleanup-order

    Using acquisition and cleanup order

    A using initializer is evaluated once. After successful acquisition, its automatic close is registered before the body. An initializer that propagates an Err registers no close for that resource. Body defers run before its close under the scope cleanup rule, including ? propagation. Capturing the File does not keep it open beyond the using scope. Ordinary runtime faults follow the fault cleanup rule.

    Ordinary runtime faults follow the fault cleanup rule.

    A deadline discards remaining using cleanup under abandoned arm cleanup. The runtime reclaims the abandoned arm's host resource handles when the group finishes.

    Причина

    Body defers may still need the resource. Running them before close and leaving nested scopes from inside to outside keeps those dependencies alive.

    Правилоtopaz.rule.structures.source.using-close-boundaries

    Explicit close and failure boundaries

    using keeps automatic File.close registered after an explicit close.

    File.close follows the File resource contract. That contract defines repeated close, shared closed state and close faults.

    The scope cleanup rule defines cleanup order, structured exits and retained body values. Ordinary runtime faults follow the fault cleanup rule.

    Deferred runtime and host errors follow the run exit contract and test result contract. These contracts determine process failure and test output independently of the stored body value.

    Deadline abandonment follows abandoned arm cleanup. It skips remaining using cleanup while the runtime reclaims the arm's host handles when the group finishes.

    At the cited native-host source revision, close sets the shared closed flag. Repeating that assignment preserves the closed state. Later reads and writes report a closed file. The File resource contract defines the required behavior across hosts.

    A deadline discards remaining using cleanup under abandoned arm cleanup. The runtime reclaims the abandoned arm's host resource handles when the group finishes.

    Причина

    Cleanup registration belongs to the scope, so an explicit close does not cancel it. The File resource contract owns the result of closing. Command contracts own exit status and test output.

    Complete examples

    Ссылка

    Implement and call a protocol

    Ссылка
    example.tpzImplement and call a protocol
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item { name: string }
    5. impl Labelled<Item> {
    6. function label(value: Item) -> string { value.name }
    7. }
    8. let text: string = Labelled.label(Item { name: "Moss" })
    Зафиксированный выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 0.

    Наблюдаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Нет вывода ошибок.

    • Пройдено · expected 0; observed 0
    • Пройдено · stdout matches the authored expectation
    • Пройдено · stderr matches the authored expectation

    Reject an explicit protocol receiver binder

    Ссылка
    example.tpzReject an explicit protocol receiver binderОткрыть песочницу →
    1. protocol Labelled<T> {
    2. function label(value: T) -> string
    3. }
    4. record Item { name: string }
    5. impl Labelled<Item> {
    6. function label(value: Item) -> string { value.name }
    7. }
    8. let text: string = Labelled.label(Item { name: "Moss" })
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения parse. Ненулевой код завершения.

    • TPZ2001 →

      protocol-explicit-receiver-binder at example.tpz:1:18

    Use Self for the conforming type

    Ссылка
    example.tpzUse Self for the conforming typeОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item { name: string }
    5. impl Labelled<Item> {
    6. function label(value: Item) -> string { value.name }
    7. }
    8. let text: string = Labelled.label(Item { name: "Moss" })
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Declare a receiver method

    Ссылка
    example.tpzDeclare a receiver method
    1. record Item { name: string }
    2. impl Item {
    3. function label(self) -> string { self.name }
    4. }
    5. let item = Item { name: "Moss" }
    6. let text: string = item.label()
    Зафиксированный выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 0.

    Наблюдаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Нет вывода ошибок.

    • Пройдено · expected 0; observed 0
    • Пройдено · stdout matches the authored expectation
    • Пройдено · stderr matches the authored expectation

    Derive built-in protocols

    Ссылка
    example.tpzDerive built-in protocols
    1. record Pair derives Eq, Order, Show, JSON {
    2. left: int,
    3. right: int,
    4. }
    5. let pair = Pair { left: 1, right: 2 }
    6. let same: bool = Eq.equals(pair, pair)
    Зафиксированный выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 0.

    Наблюдаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Нет вывода ошибок.

    • Пройдено · expected 0; observed 0
    • Пройдено · stdout matches the authored expectation
    • Пройдено · stderr matches the authored expectation

    Check a File resource binding

    Ссылка
    example.tpzCheck a File resource binding
    1. function manage(file: File) -> () {
    2. using resource = (file) {
    3. let handle: File = resource
    4. }
    5. }
    Зафиксированный выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 0.

    Наблюдаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Нет вывода ошибок.

    • Пройдено · expected 0; observed 0
    • Пройдено · stdout matches the authored expectation
    • Пройдено · stderr matches the authored expectation

    Reject an incomplete implementation

    Ссылка
    example.tpzReject an incomplete implementationОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item { name: string }
    5. impl Labelled<Item> {}
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5022]: `impl Labelled<Item>` is missing method `label`
     --> example.tpz:7:6
      |
    7 | impl Labelled<Item> {}
      |      ^^^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 1.

    Нет стандартного вывода.

    Наблюдаемый вывод ошибок
    1. error[TPZ5022]: `impl Labelled<Item>` is missing method `label`
    2. --> example.tpz:7:6
    3. |
    4. 7 | impl Labelled<Item> {}
    5. | ^^^^^^^^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5022; cause missing-protocol-method; primary location asserted; additional diagnostics allow

    A foreign protocol on a foreign type violates ownership

    Ссылка
    example.tpzA foreign protocol on a foreign type violates ownershipОткрыть песочницу →
    1. impl Show<int> {
    2. function show(value: int) -> string { "number" }
    3. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5520 →

      protocol-orphan-implementation at example.tpz:1:11

    The preserved receipt belongs to an earlier revision that rejected a local protocol on int. This revision checks the orphan case where both Show and int belong to another module. The 6.0 contract permits the local-protocol case shown separately.

    Reject a repeated conformance

    Ссылка
    example.tpzReject a repeated conformanceОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item { name: string }
    5. impl Labelled<Item> {
    6. function label(value: Item) -> string { value.name }
    7. }
    8. impl Labelled<Item> {
    9. function label(value: Item) -> string { value.name }
    10. }
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5521]: `Item` already conforms to `Labelled` by a previous `impl`; a conformance must be unique
      --> example.tpz:11:15
       |
    11 | impl Labelled<Item> {
       |               ^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      duplicate-protocol-conformance at example.tpz:11:15

    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 1.

    Нет стандартного вывода.

    Наблюдаемый вывод ошибок
    1. error[TPZ5521]: `Item` already conforms to `Labelled` by a previous `impl`; a conformance must be unique
    2. --> example.tpz:11:15
    3. |
    4. 11 | impl Labelled<Item> {
    5. | ^^^^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5521; cause duplicate-protocol-conformance; primary location asserted; additional diagnostics allow

    Reject a call without conformance

    Ссылка
    example.tpzReject a call without conformanceОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item { name: string }
    5. let text: string = Labelled.label(Item { name: "Moss" })
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5522]: `Item` does not conform to `Labelled`
     --> example.tpz:7:35
      |
    7 | let text: string = Labelled.label(Item { name: "Moss" })
      |                                   ^^^^^^^^^^^^^^^^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5522 →

      protocol-call-argument-does-not-conform at example.tpz:7:35

    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 1.

    Нет стандартного вывода.

    Наблюдаемый вывод ошибок
    1. error[TPZ5522]: `Item` does not conform to `Labelled`
    2. --> example.tpz:7:35
    3. |
    4. 7 | let text: string = Labelled.label(Item { name: "Moss" })
    5. | ^^^^^^^^^^^^^^^^^^^^^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5522; cause protocol-call-argument-does-not-conform; primary location asserted; additional diagnostics allow

    Reject a user-defined protocol in derives

    Ссылка
    example.tpzReject a user-defined protocol in derivesОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item derives Labelled { name: string }
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5530]: unknown protocol `Labelled` in `derives` for `Item`; derivable protocols are `Eq`, `Order`, `Show`, `JSON`
     --> example.tpz:5:21
      |
    5 | record Item derives Labelled { name: string }
      |                     ^^^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      protocol-is-not-derivable at example.tpz:5:21

    Наблюдаемые утверждения · Пройдено · 5.21.3

    Код завершения 1.

    Нет стандартного вывода.

    Наблюдаемый вывод ошибок
    1. error[TPZ5530]: unknown protocol `Labelled` in `derives` for `Item`; derivable protocols are `Eq`, `Order`, `Show`, `JSON`
    2. --> example.tpz:5:21
    3. |
    4. 5 | record Item derives Labelled { name: string }
    5. | ^^^^^^^^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5530; cause protocol-is-not-derivable; primary location asserted; additional diagnostics allow

    Acquire once, run body defers, then close

    Ссылка
    example.tpzAcquire once, run body defers, then closeОткрыть песочницу →
    1. import std.io
    2. let mut acquisitions = 0
    3. let mut later: () -> string = () => "unset"
    4. function acquire() -> Result<File, string> {
    5. acquisitions += 1
    6. io.open("input.txt")
    7. }
    8. function scenario() -> Result<int, string> {
    9. using file = (acquire()?) {
    10. later = () => match (file.read()) {
    11. case Ok(text) => text
    12. case Err(e) => e
    13. }
    14. defer { io.writeLine(match (file.read()) {
    15. case Ok(text) => "defer:{text}"
    16. case Err(e) => "defer:{e}"
    17. }) }
    18. io.writeLine("body")
    19. 99
    20. }
    21. Ok(7)
    22. }
    23. let ignored = scenario()
    24. io.writeLine("acquisitions:{acquisitions}")
    25. io.writeLine(later())
    Ожидаемый выводКод завершения 0
    body
    defer:payload
    acquisitions:1
    file is closed
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    input.txtAcquire once, run body defers, then closeОткрыть песочницу →
    1. payload
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. body
    2. defer:payload
    3. acquisitions:1
    4. file is closed

    Close on return, propagation, break, and continue

    Ссылка
    example.tpzClose on return, propagation, break, and continueОткрыть песочницу →
    1. import std.io
    2. let mut later: () -> string = () => "unset"
    3. function fail() -> Result<int, string> { Err("stop") }
    4. function onReturn() -> Result<int, string> {
    5. using file = (io.open("input.txt")?) {
    6. later = () => match (file.read()) {
    7. case Ok(text) => text
    8. case Err(e) => e
    9. }
    10. return Ok(7)
    11. }
    12. Ok(0)
    13. }
    14. let ignoredonReturn = onReturn()
    15. io.writeLine("onReturn:{later()}")
    16. function onQuestion() -> Result<int, string> {
    17. using file = (io.open("input.txt")?) {
    18. later = () => match (file.read()) {
    19. case Ok(text) => text
    20. case Err(e) => e
    21. }
    22. fail()?
    23. }
    24. Ok(0)
    25. }
    26. let ignoredonQuestion = onQuestion()
    27. io.writeLine("onQuestion:{later()}")
    28. function onBreak() -> Result<int, string> {
    29. let mut i = 0
    30. while (i < 1) {
    31. using file = (io.open("input.txt")?) {
    32. later = () => match (file.read()) {
    33. case Ok(text) => text
    34. case Err(e) => e
    35. }
    36. break
    37. }
    38. }
    39. Ok(0)
    40. }
    41. let ignoredonBreak = onBreak()
    42. io.writeLine("onBreak:{later()}")
    43. function onContinue() -> Result<int, string> {
    44. let mut i = 0
    45. while (i < 1) {
    46. using file = (io.open("input.txt")?) {
    47. later = () => match (file.read()) {
    48. case Ok(text) => text
    49. case Err(e) => e
    50. }
    51. i += 1
    52. continue
    53. }
    54. }
    55. Ok(0)
    56. }
    57. let ignoredonContinue = onContinue()
    58. io.writeLine("onContinue:{later()}")
    Ожидаемый выводКод завершения 0
    onReturn:file is closed
    onQuestion:file is closed
    onBreak:file is closed
    onContinue:file is closed
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    input.txtClose on return, propagation, break, and continueОткрыть песочницу →
    1. payload
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. onReturn:file is closed
    2. onQuestion:file is closed
    3. onBreak:file is closed
    4. onContinue:file is closed

    Explicit and automatic close on the installed native host

    Ссылка
    example.tpzExplicit and automatic close on the installed native hostОткрыть песочницу →
    1. import std.io
    2. let mut later: () -> string = () => "unset"
    3. function scenario() -> Result<int, string> {
    4. using file = (io.open("input.txt")?) {
    5. later = () => match (file.read()) {
    6. case Ok(text) => text
    7. case Err(e) => e
    8. }
    9. file.close()
    10. file.close()
    11. io.writeLine(later())
    12. }
    13. Ok(0)
    14. }
    15. let ignored = scenario()
    16. io.writeLine(later())
    Ожидаемый выводКод завершения 0
    file is closed
    file is closed
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    input.txtExplicit and automatic close on the installed native hostОткрыть песочницу →
    1. payload
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. file is closed
    2. file is closed

    This example tests repeated close on the installed native host. The File resource contract requires the same close result across hosts.

    Reject a non-File resource initializer

    Ссылка
    example.tpzReject a non-File resource initializerОткрыть песочницу →
    1. using resource = (1) {}
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5001 →

      structures-using-requires-file at example.tpz:1:19

    Use a File resource initializer

    Ссылка
    example.tpzUse a File resource initializer
    1. function manage(file: File) -> () {
    2. using resource = (file) {}
    3. }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Check nested concrete members and recursive Eq or Order

    Ссылка
    example.tpzCheck nested concrete members and recursive Eq or Order
    1. record Leaf derives Eq, Order, JSON { value: int }
    2. record Box derives Eq, Order, JSON { value: Leaf }
    3. record Nested derives Eq, Order, Show, JSON { value: Box }
    4. enum Tree derives Eq, Show { Leaf(int), Branch(Array<Tree>) }
    5. enum Chain derives Eq, Order { End, Next(int, Chain) }
    6. record Callable derives Show { run: () -> int }
    7. record Document derives Eq, JSON { items: Array<Option<Leaf>> }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Map value equality satisfies Eq derivation

    Ссылка
    example.tpzMap value equality satisfies Eq derivationОткрыть песочницу →
    1. record Index derives Eq { values: Map<string, int> }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Use comparable array elements

    Ссылка
    example.tpzUse comparable array elements
    1. record Comparable derives Eq { values: Array<int> }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Reject a float field when deriving total Order

    Ссылка
    example.tpzReject a float field when deriving total OrderОткрыть песочницу →
    1. record NonTotal derives Order { value: float }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5530 →

      structures-derive-order-field at example.tpz:1:25

    Use a totally orderable field

    Ссылка
    example.tpzUse a totally orderable field
    1. record Total derives Order { value: int }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    A recursive declaration has a reusable JSON conformance

    Ссылка
    example.tpzA recursive declaration has a reusable JSON conformanceОткрыть песочницу →
    1. enum Recursive derives JSON { End, Next(Recursive) }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Use finite JSON payloads

    Ссылка
    example.tpzUse finite JSON payloads
    1. enum Finite derives JSON { End, Value(int) }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    A nested manual Eq implementation satisfies outer derivation

    Ссылка
    example.tpzA nested manual Eq implementation satisfies outer derivationОткрыть песочницу →
    1. record Callback { run: () -> int }
    2. impl Eq<Callback> {
    3. function equals(a: Callback, b: Callback) -> bool { true }
    4. }
    5. record Outer derives Eq { item: Callback }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Show does not require nested comparability

    Ссылка
    example.tpzShow does not require nested comparability
    1. record Callback { run: () -> int }
    2. impl Eq<Callback> {
    3. function equals(a: Callback, b: Callback) -> bool { true }
    4. }
    5. record Outer derives Show { item: Callback }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Reject duplicate manual and derived Eq

    Ссылка
    example.tpzReject duplicate manual and derived EqОткрыть песочницу →
    1. record Item derives Eq { value: int }
    2. impl Eq<Item> {
    3. function equals(a: Item, b: Item) -> bool { a.value == b.value }
    4. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      structures-duplicate-conformance at example.tpz:1:21

    Keep one conformance per protocol

    Ссылка
    example.tpzKeep one conformance per protocol
    1. record Item derives Show { value: int }
    2. impl Eq<Item> {
    3. function equals(a: Item, b: Item) -> bool { a.value == b.value }
    4. }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Null supports Eq and JSON derivation

    Ссылка
    example.tpzNull supports Eq and JSON derivation
    1. record Nil derives Eq, JSON { value: null }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    An imported nominal alias keeps its derived conformance

    Ссылка
    example.tpzAn imported nominal alias keeps its derived conformanceОткрыть песочницу →
    1. import remote { Item as RemoteItem }
    2. record Item { n: int }
    3. let imported = RemoteItem { n: 1 }
    4. let same: bool = Eq.equals(imported, imported)
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (2 modules)
    example.tpz: resolve-ok (2 modules)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    remote.tpzAn imported nominal alias keeps its derived conformanceОткрыть песочницу →
    1. export record Item derives Eq { n: int }
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (2 modules)
    2. example.tpz: resolve-ok (2 modules)

    A local type does not inherit the imported namesake conformance

    Ссылка
    example.tpzA local type does not inherit the imported namesake conformanceОткрыть песочницу →
    1. import remote { Item as RemoteItem }
    2. record Item { n: int }
    3. let localValue = Item { n: 1 }
    4. let same = Eq.equals(localValue, localValue)
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    remote.tpzA local type does not inherit the imported namesake conformanceОткрыть песочницу →
    1. export record Item derives Eq { n: int }
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5522 →

      structures-no-visible-eq-conformance at example.tpz:4:22

    Give the local type its own conformance

    Ссылка
    example.tpzGive the local type its own conformanceОткрыть песочницу →
    1. import remote { Item as RemoteItem }
    2. record Item derives Eq { n: int }
    3. let localValue = Item { n: 1 }
    4. let same = Eq.equals(localValue, localValue)
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (2 modules)
    example.tpz: resolve-ok (2 modules)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    remote.tpzGive the local type its own conformanceОткрыть песочницу →
    1. export record Item derives Eq { n: int }
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (2 modules)
    2. example.tpz: resolve-ok (2 modules)

    A manual conformance is visible through a nominal import

    Ссылка
    example.tpzA manual conformance is visible through a nominal importОткрыть песочницу →
    1. import remote { Item as RemoteItem }
    2. let imported = RemoteItem { n: 1 }
    3. let same = Eq.equals(imported, imported)
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    remote.tpzA manual conformance is visible through a nominal importОткрыть песочницу →
    1. export record Item { n: int }
    2. impl Eq<Item> {
    3. function equals(a: Item, b: Item) -> bool { a.n == b.n }
    4. }
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    A derived conformance is visible through a nominal import

    Ссылка
    example.tpzA derived conformance is visible through a nominal importОткрыть песочницу →
    1. import remote { Item as RemoteItem }
    2. let imported = RemoteItem { n: 1 }
    3. let same = Eq.equals(imported, imported)
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    remote.tpzA derived conformance is visible through a nominal importОткрыть песочницу →
    1. export record Item derives Eq { n: int }
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    A local value owns the member call despite a protocol namesake

    Ссылка
    example.tpzA local value owns the member call despite a protocol namesake
    1. import std.io
    2. protocol Labelled { function label(value: Self) -> string }
    3. record Item { name: string }
    4. impl Labelled<Item> {
    5. function label(value: Item) -> string { value.name }
    6. }
    7. function localLabel() -> string {
    8. let Labelled = { label: (value: Item) => "local" }
    9. Labelled.label(Item { name: "protocol" })
    10. }
    11. io.writeLine(localLabel())
    Ожидаемый выводКод завершения 0
    local
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. local

    Reject a user protocol with a built-in protocol name

    Ссылка
    example.tpzReject a user protocol with a built-in protocol nameОткрыть песочницу →
    1. protocol Eq { function custom(value: Self) -> int }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5008 →

      structures-builtin-protocol-redeclaration at example.tpz:1:10

    Choose a distinct user protocol name

    Ссылка
    example.tpzChoose a distinct user protocol name
    1. protocol Custom { function custom(value: Self) -> int }
    Ожидаемый выводКод завершения 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Ожидаемый стандартный вывод
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    Evaluate the return value, then close nested resources

    Ссылка
    example.tpzEvaluate the return value, then close nested resourcesОткрыть песочницу →
    1. import std.io
    2. let mut outerClosed: () -> bool = () => false
    3. let mut innerClosed: () -> bool = () => false
    4. function isClosed(file: File) -> bool {
    5. match (file.read()) {
    6. case Ok(text) => false
    7. case Err(error) => true
    8. }
    9. }
    10. function makeResult() -> Result<int, string> {
    11. io.writeLine("return-value")
    12. Ok(7)
    13. }
    14. function scenario() -> Result<int, string> {
    15. using outer = (io.open("input.txt")?) {
    16. outerClosed = () => isClosed(outer)
    17. defer { io.writeLine("outer-defer:inner-closed={innerClosed()}") }
    18. using inner = (io.open("input.txt")?) {
    19. innerClosed = () => isClosed(inner)
    20. defer { io.writeLine("inner-defer") }
    21. return makeResult()
    22. }
    23. }
    24. Ok(0)
    25. }
    26. let outcome = scenario()
    27. io.writeLine(match (outcome) {
    28. case Ok(value) => "result:{value}"
    29. case Err(error) => "open:{error}"
    30. })
    31. io.writeLine("outer-closed:{outerClosed()}")
    32. io.writeLine("inner-closed:{innerClosed()}")
    Ожидаемый выводКод завершения 0
    return-value
    inner-defer
    outer-defer:inner-closed=true
    result:7
    outer-closed:true
    inner-closed:true
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    input.txtEvaluate the return value, then close nested resourcesОткрыть песочницу →
    1. payload
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. return-value
    2. inner-defer
    3. outer-defer:inner-closed=true
    4. result:7
    5. outer-closed:true
    6. inner-closed:true

    The native File read result makes closing observable. The outer body defer sees the inner resource closed before the outer resource closes.

    An ordinary fault skips remaining cleanup

    Ссылка
    example.tpzAn ordinary fault skips remaining cleanupОткрыть песочницу →
    1. import std.io
    2. function divide(divisor: int) -> int {
    3. 42 / divisor
    4. }
    5. function scenario() -> Result<int, string> {
    6. using file = (io.open("input.txt")?) {
    7. defer { io.writeLine("cleanup-observed") }
    8. divide(0)
    9. }
    10. Ok(0)
    11. }
    12. let result = scenario()
    Ожидаемый выводКод завершения 1
    Нет стандартного вывода.
    $ topaz run example.tpz · Целевой продукт 5.21.3
    input.txtAn ordinary fault skips remaining cleanupОткрыть песочницу →
    1. payload
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения run. Код завершения 1.

    The division fault stops execution. The remaining defer and using cleanup are skipped under the fault cleanup rule. Standard output contains no cleanup message.

    An imported protocol call executes its manual method

    Ссылка
    example.tpzAn imported protocol call executes its manual methodОткрыть песочницу →
    1. import std.io { writeLine }
    2. import remote { Item as RemoteItem }
    3. let left = RemoteItem { n: 1 }
    4. let right = RemoteItem { n: 11 }
    5. writeLine("{Eq.equals(left, right)}")
    Ожидаемый выводКод завершения 0
    true
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    remote.tpzAn imported protocol call executes its manual methodОткрыть песочницу →
    1. export record Item { n: int }
    2. impl Eq<Item> {
    3. function equals(a: Item, b: Item) -> bool { a.n % 10 == b.n % 10 }
    4. }
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. true

    A protocol method has ordinary generic bounds

    Ссылка
    example.tpzA protocol method has ordinary generic boundsОткрыть песочницу →
    1. protocol Echo {
    2. function echo<T: Show>(value: Self, item: T) -> T
    3. }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Fixed defaults precede the variadic protocol tail

    Ссылка
    example.tpzFixed defaults precede the variadic protocol tailОткрыть песочницу →
    1. protocol Sum {
    2. function sum(value: Self, start: int = 0, ...items: int) -> int
    3. }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Every caller uses the protocol-owned default

    Ссылка
    example.tpzEvery caller uses the protocol-owned default
    1. import std.io { writeLine }
    2. const ending = "!"
    3. protocol Labelled {
    4. function label(value: Self, suffix: string = ending) -> string
    5. }
    6. record Item { name: string }
    7. impl Labelled<Item> {
    8. function label(value: Item, suffix: string) -> string { value.name + suffix }
    9. }
    10. let item = Item { name: "Moss" }
    11. writeLine(Labelled.label(item))
    12. writeLine(Labelled.label(item, "?"))
    Ожидаемый выводКод завершения 0
    Moss!
    Moss?
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. Moss!
    2. Moss?

    A protocol constructs a value without a receiver argument

    Ссылка
    example.tpzA protocol constructs a value without a receiver argument
    1. import std.io { writeLine }
    2. protocol Factory {
    3. function make(value: int) -> Self
    4. function zero() -> Self
    5. }
    6. record Item { value: int }
    7. impl Factory<Item> {
    8. function make(value: int) -> Item { Item { value: value } }
    9. function zero() -> Item { Item { value: 0 } }
    10. }
    11. let explicit = Factory.make<Item>(9)
    12. let inferred: Item = Factory.zero()
    13. writeLine("{explicit.value}")
    14. writeLine("{inferred.value}")
    Ожидаемый выводКод завершения 0
    9
    0
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. 9
    2. 0

    Protocol calls reject named arguments during parsing

    Ссылка
    example.tpzProtocol calls reject named arguments during parsingОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item { name: string }
    5. impl Labelled<Item> {
    6. function label(value: Item) -> string { value.name }
    7. }
    8. let item = Item { name: "Moss" }
    9. Labelled.label(value: item)
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения parse. Ненулевой код завершения.

    • TPZ2001 →

      function-named-call-syntax at example.tpz:9:21

    A required protocol parameter cannot follow a default

    Ссылка
    example.tpzA required protocol parameter cannot follow a defaultОткрыть песочницу →
    1. protocol Sum {
    2. function sum(value: Self, first: int = 1, second: int) -> int
    3. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения parse. Ненулевой код завершения.

    • TPZ2001 →

      function-required-after-default at example.tpz:2:58

    A bodyless protocol signature still declares its result

    Ссылка
    example.tpzA bodyless protocol signature still declares its resultОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self)
    3. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5022 →

      protocol-signature-return-required at example.tpz:2:14

    Implementation binders and renamed method binders remain distinct

    Ссылка
    example.tpzImplementation binders and renamed method binders remain distinct
    1. import std.io { writeLine }
    2. protocol Echo {
    3. function echo<U: Show>(value: Self, item: U) -> U
    4. }
    5. record Box<T> { value: T }
    6. impl<T> Echo<Box<T>> {
    7. function echo<V: Show>(value: Box<T>, item: V) { item }
    8. }
    9. let box: Box<int> = Box { value: 3 }
    10. writeLine(Echo.echo<Box<int>, string>(box, "ok"))
    11. let inferred: int = Echo.echo(box, 9)
    12. writeLine("{inferred}")
    Ожидаемый выводКод завершения 0
    ok
    9
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. ok
    2. 9

    Protocol defaults and a variadic implementation share one call plan

    Ссылка
    example.tpzProtocol defaults and a variadic implementation share one call plan
    1. import std.io { writeLine }
    2. protocol Sum {
    3. function sum(value: Self, start: int = 10, ...items: int) -> int
    4. }
    5. record Item { offset: int }
    6. impl Sum<Item> {
    7. function sum(value: Item, start: int, ...items: int) {
    8. let mut total = value.offset + start
    9. for item in (items) { total = total + item }
    10. total
    11. }
    12. }
    13. let item = Item { offset: 1 }
    14. writeLine("{Sum.sum(item)}")
    15. writeLine("{Sum.sum(item, 2, ...[3, 4], 5)}")
    16. writeLine("{Sum.sum(item, ...[2, 3])}")
    Ожидаемый выводКод завершения 0
    11
    15
    16
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. 11
    2. 15
    3. 16

    An omitted implementation result uses the protocol result context

    Ссылка
    example.tpzAn omitted implementation result uses the protocol result contextОткрыть песочницу →
    1. protocol Choose {
    2. function choose(value: Self) -> int | string
    3. }
    4. record Item {}
    5. impl Choose<Item> {
    6. function choose(value: Item) { 7 }
    7. }
    8. let chosen: int | string = Choose.choose(Item {})
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    A generic receiver keeps its outer binder and local method binders

    Ссылка
    example.tpzA generic receiver keeps its outer binder and local method binders
    1. import std.io { writeLine }
    2. record Box<T> { value: T }
    3. impl<T> Box<T> {
    4. function readValue(self) -> T { self.value }
    5. function echo<U>(self, item: U) -> U { item }
    6. }
    7. let box: Box<int> = Box { value: 3 }
    8. writeLine("{box.readValue()}")
    9. writeLine(box.echo<string>("ok"))
    Ожидаемый выводКод завершения 0
    3
    ok
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. 3
    2. ok

    A protocol owner can give int its declared operation

    Ссылка
    example.tpzA protocol owner can give int its declared operation
    1. import std.io { writeLine }
    2. protocol Labelled {
    3. function label(value: Self) -> string
    4. }
    5. impl Labelled<int> {
    6. function label(value: int) -> string { "number" }
    7. }
    8. writeLine(Labelled.label(7))
    Ожидаемый выводКод завершения 0
    number
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. number

    Different concrete type arguments select distinct conformances

    Ссылка
    example.tpzDifferent concrete type arguments select distinct conformances
    1. import std.io { writeLine }
    2. protocol Mark {
    3. function mark(value: Self) -> string
    4. }
    5. record Box<T> { value: T }
    6. impl Mark<Box<int>> {
    7. function mark(value: Box<int>) -> string { "integer" }
    8. }
    9. impl Mark<Box<string>> {
    10. function mark(value: Box<string>) -> string { "text" }
    11. }
    12. let number: Box<int> = Box { value: 3 }
    13. let text: Box<string> = Box { value: "three" }
    14. writeLine(Mark.mark(number))
    15. writeLine(Mark.mark(text))
    Ожидаемый выводКод завершения 0
    integer
    text
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Выполнение завершается. Код завершения 0.

    Ожидаемый стандартный вывод
    1. integer
    2. text

    Conditional derive binders correspond by position without capturing fields

    Ссылка
    example.tpzConditional derive binders correspond by position without capturing fieldsОткрыть песочницу →
    1. record Box<T> derives<U: Eq> Eq<Box<U>> { value: T }
    2. let first: Box<int> = Box { value: 3 }
    3. let second: Box<int> = Box { value: 3 }
    4. let same: bool = Eq.equals(first, second)
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Проверка принимает программу. Код завершения 0.

    Conformance visibility makes a separate method export invalid

    Ссылка
    example.tpzConformance visibility makes a separate method export invalidОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self) -> string
    3. }
    4. record Item {}
    5. impl Labelled<Item> {
    6. export function label(value: Item) -> string { "item" }
    7. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    An implementation cannot introduce its own omitted argument

    Ссылка
    example.tpzAn implementation cannot introduce its own omitted argumentОткрыть песочницу →
    1. protocol Labelled {
    2. function label(value: Self, suffix: string) -> string
    3. }
    4. record Item {}
    5. impl Labelled<Item> {
    6. function label(value: Item, suffix: string = "!") -> string { suffix }
    7. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    Implementation method bounds must match the declared operation

    Ссылка
    example.tpzImplementation method bounds must match the declared operationОткрыть песочницу →
    1. protocol Echo {
    2. function echo<U: Show>(value: Self, item: U) -> U
    3. }
    4. record Item {}
    5. impl Echo<Item> {
    6. function echo<V: Eq>(value: Item, item: V) -> V { item }
    7. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5022 →

      protocol-method-signature-mismatch at example.tpz:6:14

    An array parameter does not replace a variadic tail

    Ссылка
    example.tpzAn array parameter does not replace a variadic tailОткрыть песочницу →
    1. protocol Count {
    2. function count(value: Self, ...items: int) -> int
    3. }
    4. record Item {}
    5. impl Count<Item> {
    6. function count(value: Item, items: Array<int>) -> int { items.length }
    7. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5022 →

      protocol-method-signature-mismatch at example.tpz:6:14

    An inner binder cannot be mistaken for the receiver binder

    Ссылка
    example.tpzAn inner binder cannot be mistaken for the receiver binderОткрыть песочницу →
    1. protocol Echo {
    2. function echo<U>(value: Self, item: U) -> U
    3. }
    4. record Box<T> { value: T }
    5. impl<T> Echo<Box<T>> {
    6. function echo<T>(value: Box<T>, item: T) -> T { item }
    7. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5022 →

      protocol-method-signature-mismatch at example.tpz:6:14

    A concrete conformance cannot specialize an overlapping generic head

    Ссылка
    example.tpzA concrete conformance cannot specialize an overlapping generic headОткрыть песочницу →
    1. record Box<T> { value: T }
    2. impl<T: Eq> Eq<Box<T>> {
    3. function equals(a: Box<T>, b: Box<T>) -> bool { Eq.equals(a.value, b.value) }
    4. }
    5. impl Eq<Box<int>> {
    6. function equals(a: Box<int>, b: Box<int>) -> bool { a.value == b.value }
    7. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      duplicate-protocol-conformance at example.tpz:5:9

    Different positive bounds do not prove two heads disjoint

    Ссылка
    example.tpzDifferent positive bounds do not prove two heads disjointОткрыть песочницу →
    1. protocol Mark {
    2. function mark(value: Self) -> int
    3. }
    4. record Box<T> { value: T }
    5. impl<T: Eq> Mark<Box<T>> {
    6. function mark(value: Box<T>) -> int { 1 }
    7. }
    8. impl<U: Show> Mark<Box<U>> {
    9. function mark(value: Box<U>) -> int { 2 }
    10. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      duplicate-protocol-conformance at example.tpz:8:20

    A conditional derive and a manual specialization share the overlap check

    Ссылка
    example.tpzA conditional derive and a manual specialization share the overlap checkОткрыть песочницу →
    1. record Box<T> derives<T: Eq> Eq<Box<T>> { value: T }
    2. impl Eq<Box<int>> {
    3. function equals(a: Box<int>, b: Box<int>) -> bool { a.value == b.value }
    4. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      duplicate-protocol-conformance at example.tpz:1:30

    A transparent alias cannot create a second conformance

    Ссылка
    example.tpzA transparent alias cannot create a second conformanceОткрыть песочницу →
    1. record Item {}
    2. type Alias = Item
    3. impl Eq<Item> {
    4. function equals(a: Item, b: Item) -> bool { true }
    5. }
    6. impl Eq<Alias> {
    7. function equals(a: Alias, b: Alias) -> bool { true }
    8. }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      duplicate-protocol-conformance at example.tpz:6:9

    The dependency graph rejects protocol-owner and type-owner overlap

    Ссылка
    example.tpzThe dependency graph rejects protocol-owner and type-owner overlapОткрыть песочницу →
    1. import rules
    2. import kinds
    3. let value = 0
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    rules.tpzThe dependency graph rejects protocol-owner and type-owner overlapОткрыть песочницу →
    1. export protocol Mark { function mark(value: Self) -> int }
    2. impl<T> Mark<T> { function mark(value: T) -> int { 1 } }
    kinds.tpzThe dependency graph rejects protocol-owner and type-owner overlapОткрыть песочницу →
    1. import rules { Mark }
    2. export record Item {}
    3. impl Mark<Item> { function mark(value: Item) -> int { 2 } }
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      duplicate-protocol-conformance at kinds.tpz:3:11

    Changing import order cannot choose a conformance winner

    Ссылка
    example.tpzChanging import order cannot choose a conformance winnerОткрыть песочницу →
    1. import kinds
    2. import rules
    3. let value = 0
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    rules.tpzChanging import order cannot choose a conformance winnerОткрыть песочницу →
    1. export protocol Mark { function mark(value: Self) -> int }
    2. impl<T> Mark<T> { function mark(value: T) -> int { 1 } }
    kinds.tpzChanging import order cannot choose a conformance winnerОткрыть песочницу →
    1. import rules { Mark }
    2. export record Item {}
    3. impl Mark<Item> { function mark(value: Item) -> int { 2 } }
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5521 →

      duplicate-protocol-conformance at kinds.tpz:3:11

    An implementation cannot assume its own conditional bound

    Ссылка
    example.tpzAn implementation cannot assume its own conditional boundОткрыть песочницу →
    1. protocol Required { function required(value: Self) -> bool }
    2. protocol Mark { function mark(value: Self) -> int }
    3. record Box<T> { value: T }
    4. impl<T: Required> Mark<Box<T>> {
    5. function mark(value: Box<T>) -> int { 1 }
    6. }
    7. let box: Box<int> = Box { value: 3 }
    8. Mark.mark(box)
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

    Ожидаемый результат

    Этап отклонения check. Ненулевой код завершения.

    • TPZ5522 →

      protocol-call-argument-does-not-conform at example.tpz:8:11

    Pending contracts

    Ссылка

    Related definitions and diagnostics

    Ссылка

    See Functions and generics for function and bound syntax, and Records, enums and newtypes for nominal construction and declaration syntax.

    Protocol implementation violates the orphan rule →

    Duplicate protocol implementation →

    Missing protocol conformance →

    Protocol cannot be derived for this type →

    TPZ5022 →

    Redeclaration →

    Wrong argument count →

    TPZ5001 →

    Division or remainder by zero →

    Unexpected token →

    Variadic parameter is not final →

    Wrong number of explicit type arguments →

    TPZ5523 →

    Module namespace collision →

    Name is not exported →

    TPZ5524 →

    Private type in exported surface →

    Unknown member or field →

    Value is not comparable or keyable →

    Runtime comparison guard →

    Меню

    Загрузка →