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

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

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

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

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

    Язык · 3 главы · 32 правила

    Типы

    Defines type forms, compatibility, and shared inference rules.

    Scope and status

    Ссылка

    Use this page to choose type annotations and understand compatibility and inference.

    Bindings and scope covers declarations and assignment. Functions and generics covers argument binding, specialization, and return inference.

    Nominal value construction, protocol conformance, module lookup, literal spelling, and API operations belong to their respective references.

    Type forms

    Ссылка
    EBNF
    1. Type = PrimaryType ("|" PrimaryType)* ;
    2. PrimaryType = NamedType | LiteralType | UnitType | GroupedType | RecordType | FunctionType ;
    3. NamedType = Identifier ("." Identifier)? TypeArguments? ;
    4. TypeArguments = "<" Type ("," Type)* ">" ;
    5. UnitType = "(" ")" ;
    6. GroupedType = "(" Type ")" ;
    7. RecordType = "{" (FieldName ":" Type ("," FieldName ":" Type)* ","?)? "}" ;
    8. FunctionType = "(" FunctionTypeParameters? ")" "->" Type ;

    Hand-transcribed source grammar excerpt. Literal spellings, function-type parameter sequence restrictions, and alias declaration syntax are omitted. Checking conditions follow below.

    Правилоtopaz.rule.types.literal-type-forms

    Literal type forms

    Literal type syntax admits int, float, bool, null, string literals. A string literal type must contain no interpolation; interpolation is rejected during parsing with TPZ2001.

    Причина

    Literal types describe exact values, which supports finite choices and discriminants. Excluding interpolation keeps their identity independent of expression evaluation.

    Правилоtopaz.rule.types.unit-grouping

    Unit and grouped types

    () denotes the unit type. (T) denotes the same type as T.

    Причина

    The unit type describes computations with no result value. Grouping changes how a type expression is parsed without creating another type.

    Правилоtopaz.rule.types.empty-structural-record

    The zero-field structural record type

    A structural record type may have zero fields. In a type position, {} denotes the zero-field structural record and may appear in an annotation, alias, parameter, or function result. Structural compatibility still requires the same field-name set. This type is distinct from the unit type ().

    The ordinary expression {} remains an empty block returning unit. No empty structural record literal is introduced. An empty concurrent {} produces the zero-field structural record value.

    Причина

    A structural record type describes its field set, including the empty set. Naming that type explicitly keeps annotations, parameters, and function results consistent with the type inferred for an empty concurrent group. Unit has its existing distinct type and value. The empty expression block keeps its existing unit meaning; this rule introduces no alternative record literal.

    Type identity source observations

    Ссылка
    Правилоtopaz.rule.types.alias-expansion

    Alias expansion

    A resolved type alias denotes its body with the supplied type arguments substituted for the corresponding declared type parameters. The alias creates no new nominal identity.

    Причина

    An alias gives an existing type a reusable name. Keeping its identity transparent avoids conversions whose sole purpose would be changing that name.

    Правилоtopaz.rule.types.nominal-identity

    Nominal type identity

    Named records, enums, and newtypes retain their declaration kind, name, originating module, and type arguments. Matching fields or a matching name from another module do not establish the same type identity.

    Причина

    Named declarations represent distinct domain concepts even when their fields match. Including the defining module prevents unrelated declarations from becoming interchangeable.

    Правилоtopaz.rule.types.builtin-arity

    Compiler-owned names and type arguments

    Type namesType arguments
    int, float, string, bool0
    template, JSONValue, File, Bytes, ByteBuffer, Path, Regex, Match, TOMLValue, URL, Date, BigInt, Decimal, RoundingMode, Duration0
    Array, Set, Option1
    Map, Result2

    Each terminal name denotes a distinct type. An incorrect type argument count for a listed name produces TPZ5022.

    Причина

    A type constructor needs a fixed set of arguments to determine the values it describes. Arity checks catch missing or unrelated parameters before values are used.

    Правилоtopaz.rule.types.length-unit

    Length unit markers

    Length takes one compiler-owned marker from Pt, Mm, Cm, In and Em.

    The marker is part of type identity and differs from the unit type (). Invalid markers and argument counts produce TPZ5001.

    Physical lengths and relative lengths define their stored values and conversions.

    Причина

    A unit belongs to a length's meaning. Keeping it in the type prevents document geometry from mixing physical and font-relative lengths without conversion.

    Правилоtopaz.rule.bindings-pending.alias-cycles-and-order

    Finite alias normalization and declaration dependencies

    A transparent type alias substitutes its arguments into its body and denotes that resulting type. Alias expansion must terminate; a direct or indirect cycle is a static error identified by TPZ5023. A reference to another alias must retain the body's type constraints. An internal unresolved placeholder does not turn an alias into a type that accepts every value. The current source-order normalization defects are recorded below, including a later int alias whose constraint is lost.

    Причина

    A transparent alias needs a finite meaning. Rejecting cycles and preserving forward constraints prevents declaration order or unresolved placeholders from changing that meaning.

    Compatibility source observations

    Ссылка
    Правилоtopaz.rule.types.literal-to-primitive

    Literal values and primitive targets

    An inferred literal type in int, float, string, bool is compatible with its corresponding primitive type.

    Причина

    An exact literal value is also a member of its primitive family. This lets precise values flow into ordinary APIs without a separate conversion.

    Правилоtopaz.rule.types.primitive-identity

    Primitive compatibility

    Resolved primitive types are compatible when their names match. An int value does not implicitly convert to float, and a float value does not implicitly convert to int.

    Причина

    Implicit numeric promotion can change precision and the operations a value supports. Explicit conversion keeps those changes visible at the use site.

    Правилоtopaz.rule.types.literal-target

    Literal type targets

    A literal type target requires the same inferred literal kind and value from a resolved non-union source type. A broad primitive type does not narrow to a literal type during this comparison.

    Причина

    A literal target promises one exact value. A broader primitive type does not establish that promise without further checking.

    Правилоtopaz.rule.types.null-type

    The null literal type

    null has its own literal type. Scalar widening preserves that type.

    Причина

    Absence carries information that a primitive type cannot express. Preserving null keeps that information available to union checks and narrowing.

    Правилоtopaz.rule.types.union-compatibility

    Union compatibility

    Every member of an actual union must be compatible with the expected type. A non-union actual type is compatible with an expected union when at least one expected member accepts it. Different actual union members can match different expected members.

    Причина

    A value of a union can belong to any member. Every possible actual member must therefore be accepted by the destination.

    Правилоtopaz.rule.types.union-normalization

    Union normalization

    Union construction flattens nested unions and removes exactly equal members.

    Причина

    Nesting and repeated members do not change the values a union admits. Normalization keeps those spellings from creating different type identities.

    Правилоtopaz.rule.types.payload-constructor

    Option and Result payload compatibility

    For the same Option, Result constructor, each actual payload type must be compatible with the corresponding expected payload type.

    Причина

    A payload accepted by the destination remains safe when wrapped in the same constructor. Checking each position preserves that relationship.

    Правилоtopaz.rule.types.collection-constructor

    Typed collection compatibility

    An already typed Array, Map, Set value requires exactly equal corresponding type arguments when compared with the same expected collection constructor.

    Причина

    An already typed collection retains its element, key, and value types. Exact corresponding type arguments preserve that contract without an implicit conversion between collection types.

    Правилоtopaz.rule.types.record-compatibility

    Structural record compatibility

    Structural record types require the same set of field names and a compatible actual type for every expected field. Field order does not affect compatibility. An extra or missing field fails this comparison.

    Причина

    Field names identify the parts of a structural record. Comparing them as a set avoids making declaration order part of its meaning.

    Правилоtopaz.rule.types.function-compatibility

    Function type compatibility

    Function types require the same fixed parameter count and variadic shape. Each actual parameter type must accept the corresponding expected parameter type, including a variadic element type when present. The actual result type must be compatible with the expected result type.

    Причина

    A substitute function must accept every argument its caller may pass and return a value the caller expects.

    Правилоtopaz.rule.bindings-pending.type-boundary-matrix

    Type boundaries across functions, payloads, and aggregates

    Function parameter compatibility runs from the expected parameter type to the actual function parameter type. The result runs in the opposite direction. The same parameter direction applies to a variadic element, and fixed arity and variadic shape must match. Both Result payload positions follow the result direction.

    BoundaryAccepted formRejected form
    Function parametersA function accepting int or string used where callers pass intAn int function used where callers may pass string
    Variadic parametersWider accepted elements used through a narrower variadic typeNarrower accepted elements promised as a wider variadic type
    Result payloadsWidening either payload argumentNarrowing a declared payload union
    Nominal identityThe same declaration from the same moduleSame-spelled declarations from different modules
    Structural fieldsDistinct names in any source orderRepeating a name in a structural type or literal
    Map and Set inferenceWidened element unions, with Map keys and values inferred separatelyEmpty bare initializers with no matching expected type
    Aggregate joinsMatching components completed by another branch or an expected typeUnresolved Result components hidden inside different record shapes

    Joining aggregate branches retains their structure while solving corresponding inference variables. A missing type argument remains unresolved until another branch or the surrounding expectation supplies it. An unannotated binding whose non-function result still contains an inference variable is rejected with TPZ5020.

    Причина

    Type compatibility must remain safe through callbacks, payloads, and aggregates. Solving every missing component prevents unresolved types from admitting incompatible values.

    Shared inference source observations

    Ссылка
    Правилоtopaz.rule.types.binding-annotation

    Binding annotations supply context

    An explicit binding type annotation supplies the expected type to its initializer.

    Причина

    The declaration already states the required type. Passing it into inference resolves values whose types cannot be chosen from their syntax alone.

    Правилоtopaz.rule.types.unannotated-binding

    Unannotated binding types

    Without an annotation, const retains the inferred initializer type. A let binding widens a top-level int, float, string, bool literal type to its primitive type. Aggregate types retain the result of aggregate inference.

    Причина

    Widening a let literal allows later operations to use its primitive family. Retaining a constant's literal type lets it name an exact permitted value.

    Правилоtopaz.rule.types.expected-type-check

    Checking an expected type

    An expected type guides expression inference and refinement before compatibility is checked. Incompatible fully resolved types produce TPZ5001.

    Причина

    The surrounding use can supply information an expression lacks. Inference uses that information before checking whether the resulting value fits.

    Правилоtopaz.rule.types.sequence-inference

    Array and Set element inference

    For a nonempty Array, Set literal without element context, ordinary elements contribute their inferred types after scalar literal widening. Their union becomes the element type.

    Причина

    Every element contributes to the collection's possible contents. Widening scalar literals avoids tying ordinary collections to the exact values used to create them.

    Правилоtopaz.rule.types.map-inference

    Map key and value inference

    For a nonempty Map literal without collection context, keys and values are inferred separately. Scalar literal types widen, then key types form one union and value types form another.

    Причина

    Map keys and values have different roles. Inferring each domain separately retains which types may be looked up and which may be returned.

    Правилоtopaz.rule.types.record-inference

    Structural record field inference

    During ordinary expression checking, each distinct structural record field uses its expected field type when one is available. A field without that expectation uses its widened inferred type.

    Причина

    Each field has its own meaning and can need a different expected type. Fieldwise inference keeps that information when the surrounding record type is known.

    Правилоtopaz.rule.types.contextual-array

    Expected Array element types

    A nonempty Array literal checked against a fully resolved Array<T> expectation uses T to check its ordinary elements and retains T as the resulting element type.

    Причина

    An expected element type describes what the array may hold. Checking each element against it constructs the intended collection without an extra conversion.

    Правилоtopaz.rule.types.empty-collection-context

    Empty collections in a binding

    An empty Array, Map, Set literal adopts a matching expected collection type, including a generic parameter inside that constructor. A bare binding initializer without matching context is rejected with TPZ5020. Nested operands do not independently count as bare bindings.

    Причина

    An empty literal contains no element from which to infer a type. Requiring context prevents a guessed type from affecting later reads or mutations.

    Правилоtopaz.rule.types.branch-values

    Types contributed by if branches

    For an if expression with an else branch, value-producing branches contribute their types to the join. A terminating branch contributes no value type.

    Причина

    The result type must account for every branch that can produce a value. A branch that leaves the expression cannot contribute a result.

    Правилоtopaz.rule.types.if-without-else-unit

    The unit type of if without else

    An if expression without an else arm has the unit type in both value and statement positions. On normal completion it produces (). The selected then branch runs for its effects and its value is discarded.

    Причина

    Without an else branch there is no result on the false path. Giving both paths unit keeps the result independent of whether the condition succeeds.

    Правилоtopaz.rule.types.branch-literal-widening

    Fresh branch literal types

    Fresh scalar literal results in an if-with-else join widen before joining when there is no fully resolved expected type or literal-preserving context.

    Причина

    A conditional chooses between values at runtime. Widening fresh literals avoids assigning an ordinary result a separate exact-value type for each branch.

    Правилоtopaz.rule.types.branch-union-preservation

    Existing union domains in a join

    At the widening step of a branch join, an existing fully resolved union retains its member types.

    Причина

    An existing union may encode a deliberate set of allowed values. Widening its members would discard that constraint when control flow joins.

    Правилоtopaz.rule.types.map-lookup-fallback

    Map lookup and optional fallback

    For Map.get and a fallback supplied by ??, apply the Map lookup contract.

    The Map lookup contract defines migration from getOr. The eager-effects example preserves receiver, key and default evaluation through explicit bindings.

    Причина

    Map lookup represents absence with Option. The same coalescing operator handles that absence for every Option value. Keeping fallback evaluation in the operator gives lookup one spelling and makes its effects explicit.

    Examples and expected results

    Ссылка

    Each example is a complete example.tpz file. The expected success or rejection is independent of future observed output. All examples remain Pending. A source-backed expectation is not an executed result. Negative examples specify the intended cause and phase; their exact diagnostic locations remain unmeasured.

    Aliases, literals, unit, and a branch join

    Ссылка
    example.tpzAliases, literals, unit, and a branch joinОткрыть песочницу →
    1. type Count = int
    2. let count: Count = 3
    3. let chosen = if (true) { 1 } else { "one" }
    4. let accepted: int | string = chosen
    5. const status = "ready"
    6. let exact: "ready" = status
    7. let absent: null = null
    8. let finished: () = ()
    Зафиксированный выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

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

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

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

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

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

    An integer is not implicitly a float

    Ссылка
    example.tpzAn integer is not implicitly a floatОткрыть песочницу →
    1. let value: float = 1
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5001]: expected `float`, found `int`
     --> example.tpz:1:20
      |
    1 | let value: float = 1
      |                    ^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

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

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

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

    Наблюдаемый вывод ошибок
    1. error[TPZ5001]: expected `float`, found `int`
    2. --> example.tpz:1:20
    3. |
    4. 1 | let value: float = 1
    5. | ^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5001; cause types-int-not-float; primary location asserted; additional diagnostics allow
    • Пройдено · checking TPZ5001; cause types-int-not-float; primary location asserted; additional diagnostics allow

    Structural fields can be written in another order

    Ссылка
    example.tpzStructural fields can be written in another orderОткрыть песочницу →
    1. type Point = { x: int, y: int }
    2. let point: Point = { y: 2, x: 1 }
    Зафиксированный выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

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

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

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

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

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

    An extra structural field is a different shape

    Ссылка
    example.tpzAn extra structural field is a different shapeОткрыть песочницу →
    1. let point: { x: int } = { x: 1, y: 2 }
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5001]: expected `{ x: int }`, found `{ x: int, y: int }`
     --> example.tpz:1:25
      |
    1 | let point: { x: int } = { x: 1, y: 2 }
      |                         ^^^^^^^^^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      types-record-extra-field at example.tpz:1:25

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

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

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

    Наблюдаемый вывод ошибок
    1. error[TPZ5001]: expected `{ x: int }`, found `{ x: int, y: int }`
    2. --> example.tpz:1:25
    3. |
    4. 1 | let point: { x: int } = { x: 1, y: 2 }
    5. | ^^^^^^^^^^^^^^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5001; cause types-record-extra-field; primary location asserted; additional diagnostics allow
    • Пройдено · checking TPZ5001; cause types-record-extra-field; primary location asserted; additional diagnostics allow

    Annotations provide empty collection types

    Ссылка
    example.tpzAnnotations provide empty collection typesОткрыть песочницу →
    1. let numbers: Array<int> = []
    2. let lookup: Map<string, int> = map {}
    3. let names: Set<string> = set {}
    Зафиксированный выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

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

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

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

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

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

    A bare empty array lacks an element type

    Ссылка
    example.tpzA bare empty array lacks an element typeОткрыть песочницу →
    1. let values = []
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5020]: `[]` needs a contextual type (§22.1): annotate the binding or the expected element type
     --> example.tpz:1:14
      |
    1 | let values = []
      |              ^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

    • TPZ5020 →

      types-empty-array-needs-context at example.tpz:1:14

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

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

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

    Наблюдаемый вывод ошибок
    1. error[TPZ5020]: `[]` needs a contextual type (§22.1): annotate the binding or the expected element type
    2. --> example.tpz:1:14
    3. |
    4. 1 | let values = []
    5. | ^^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5020; cause types-empty-array-needs-context; primary location asserted; additional diagnostics allow

    An existing Array keeps its element type

    Ссылка
    example.tpzAn existing Array keeps its element typeОткрыть песочницу →
    1. let integers: Array<int> = [1]
    2. let values: Array<int | string> = integers
    Зафиксированный выводКод завершения 1
    Нет стандартного вывода.
    error[TPZ5001]: expected `Array<int | string>`, found `Array<int>`
     --> example.tpz:2:35
      |
    2 | let values: Array<int | string> = integers
      |                                   ^^^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      types-invariant-array-argument at example.tpz:2:35

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

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

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

    Наблюдаемый вывод ошибок
    1. error[TPZ5001]: expected `Array<int | string>`, found `Array<int>`
    2. --> example.tpz:2:35
    3. |
    4. 2 | let values: Array<int | string> = integers
    5. | ^^^^^^^^
    6. example.tpz: 1 type diagnostic
    • Пройдено · expected nonzero; observed 1
    • Пройдено · stdout matches the authored expectation
    • Пройдено · checking TPZ5001; cause types-invariant-array-argument; primary location asserted; additional diagnostics allow
    • Пройдено · checking TPZ5001; cause types-invariant-array-argument; primary location asserted; additional diagnostics allow

    Payload and function types use their own compatibility rules

    Ссылка
    example.tpzPayload and function types use their own compatibility rulesОткрыть песочницу →
    1. let narrow: Option<int> = Some(1)
    2. let wide: Option<int | string> = narrow
    3. function acceptsEither(value: int | string) -> int {
    4. 1
    5. }
    6. let callback: (int) -> (int | string) = acceptsEither
    Зафиксированный выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Зафиксировано с Топазом 5.21.3
    Ожидаемый результат

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

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

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

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

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

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

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

    Finite aliases substitute their type arguments

    Ссылка
    example.tpzFinite aliases substitute their type arguments
    1. import std.io
    2. type Element = int
    3. type Bag<T> = Array<T>
    4. type Counts = Bag<Element>
    5. let counts: Counts = [2, 5]
    6. io.writeLine("{counts[0]}:{counts[1]}")
    Ожидаемый выводКод завершения 0
    2:5
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

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

    Recursive alias expansion retains its intended rejection

    Ссылка
    example.tpzRecursive alias expansion retains its intended rejectionОткрыть песочницу →
    1. type First = Second
    2. type Second = First
    3. let value: First = 1
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    Контракт обязательного основного местоположения не определён.

    A later alias body must not erase an int constraint

    Ссылка
    example.tpzA later alias body must not erase an int constraintОткрыть песочницу →
    1. type First = Second
    2. type Second = int
    3. let value: First = "bad"
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      types-alias-body-mismatch at example.tpz:3:20

    A function with wider inputs fits a narrower input contract

    Ссылка
    example.tpzA function with wider inputs fits a narrower input contract
    1. import std.io
    2. function acceptsEither(value: int | string) -> int { 7 }
    3. let callback: (int) -> (int | string) = acceptsEither
    4. io.writeLine("{callback(1)}")
    Ожидаемый выводКод завершения 0
    7
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

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

    A function accepting int cannot promise to accept string

    Ссылка
    example.tpzA function accepting int cannot promise to accept stringОткрыть песочницу →
    1. function acceptsInt(value: int) -> int { value }
    2. let callback: (int | string) -> int = acceptsInt
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      types-function-parameter-variance at example.tpz:2:39

    Variadic element types follow the parameter direction

    Ссылка
    example.tpzVariadic element types follow the parameter direction
    1. import std.io
    2. function count(...values: int | string) -> int { values.length }
    3. let callback: (...int) -> int = count
    4. io.writeLine("{callback(1, 2)}")
    Ожидаемый выводКод завершения 0
    2
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

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

    A variadic int function cannot accept string elements

    Ссылка
    example.tpzA variadic int function cannot accept string elementsОткрыть песочницу →
    1. function count(...values: int) -> int { values.length }
    2. let callback: (...int | string) -> int = count
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      types-variadic-parameter-variance at example.tpz:2:42

    Both Result payload positions may widen

    Ссылка
    example.tpzBoth Result payload positions may widenОткрыть песочницу →
    1. let narrow: Result<int, string> = Ok(3)
    2. let wider: Result<int | string, string | bool> = narrow
    3. let error: Result<int, string> = Err("missing")
    4. let widerError: Result<int | string, string | bool> = error
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    A wider Result payload cannot be narrowed by assignment

    Ссылка
    example.tpzA wider Result payload cannot be narrowed by assignmentОткрыть песочницу →
    1. let broad: Result<int | string, string> = Ok("bad")
    2. let narrow: Result<int, string> = broad
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      types-result-payload-narrowing at example.tpz:2:35

    A nominal value keeps its declaring module

    Ссылка
    example.tpzA nominal value keeps its declaring moduleОткрыть песочницу →
    1. import a
    2. import b
    3. function same(value: b.Book) -> b.Book { value }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    a.tpzA nominal value keeps its declaring moduleОткрыть песочницу →
    1. export record Book { title: string }
    b.tpzA nominal value keeps its declaring moduleОткрыть песочницу →
    1. export record Book { title: string }
    Ожидаемый результат

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

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

    Same-named records from different modules remain distinct

    Ссылка
    example.tpzSame-named records from different modules remain distinctОткрыть песочницу →
    1. import a
    2. import b
    3. function wrong(value: b.Book) -> a.Book { value }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    a.tpzSame-named records from different modules remain distinctОткрыть песочницу →
    1. export record Book { title: string }
    b.tpzSame-named records from different modules remain distinctОткрыть песочницу →
    1. export record Book { title: string }
    Ожидаемый результат

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

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

    • TPZ5001 →

      types-cross-module-nominal at example.tpz:3:43

    Distinct structural fields may be written in either order

    Ссылка
    example.tpzDistinct structural fields may be written in either order
    1. import std.io
    2. let item: { value: int, label: string } = { label: "x", value: 1 }
    3. io.writeLine("{item.value}:{item.label}")
    Ожидаемый выводКод завершения 0
    1:x
    
    $ topaz run example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

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

    A structural type cannot repeat a field name

    Ссылка
    example.tpzA structural type cannot repeat a field nameОткрыть песочницу →
    1. let item: { value: int, value: string } = { value: 1 }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5022 →

      types-repeated-record-type-field at example.tpz:1:25

    A structural literal cannot repeat a field name

    Ссылка
    example.tpzA structural literal cannot repeat a field nameОткрыть песочницу →
    1. let item = { value: 1, value: 2 }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5022 →

      types-repeated-record-literal-field at example.tpz:1:24

    Map and Set infer unions and accept empty typed contexts

    Ссылка
    example.tpzMap and Set infer unions and accept empty typed contextsОткрыть песочницу →
    1. let mapping = map { 1: "one", "two": 2 }
    2. let checkedMap: Map<int | string, int | string> = mapping
    3. let members = set { 1, "two" }
    4. let checkedSet: Set<int | string> = members
    5. let emptyMap: Map<string, int> = map {}
    6. let emptySet: Set<int> = set {}
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    An unannotated empty Map leaves its arguments unresolved

    Ссылка
    example.tpzAn unannotated empty Map leaves its arguments unresolvedОткрыть песочницу →
    1. let values = map {}
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5020 →

      types-empty-map-needs-context at example.tpz:1:14

    An unannotated empty Set leaves its element unresolved

    Ссылка
    example.tpzAn unannotated empty Set leaves its element unresolvedОткрыть песочницу →
    1. let values = set {}
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5020 →

      types-empty-set-needs-context at example.tpz:1:14

    Matching record branches complete Result payload arguments

    Ссылка
    example.tpzMatching record branches complete Result payload argumentsОткрыть песочницу →
    1. let joined = if (true) { { result: Ok(1) } } else { { result: Err("missing") } }
    2. let checked: { result: Result<int, string> } = joined
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    A callback expectation supplies both Result payloads

    Ссылка
    example.tpzA callback expectation supplies both Result payloadsОткрыть песочницу →
    1. function take(f: () -> { a: Result<int, string> } | { b: Result<int, string> }) -> int { 0 }
    2. let count = take(() => if (true) { { a: Ok(1) } } else { { b: Err("e") } })
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    Different record shapes do not erase unsolved Result arguments

    Ссылка
    example.tpzDifferent record shapes do not erase unsolved Result argumentsОткрыть песочницу →
    1. let got = if (true) { { a: Ok(1) } } else { { b: Err("e") } }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5020 →

      types-unresolved-record-join at example.tpz:1:11

    An omitted else discards values and preserves selected effects

    Ссылка
    example.tpzAn omitted else discards values and preserves selected effectsОткрыть песочницу →
    1. import std.io
    2. let taken = if (true) {
    3. io.writeLine("then")
    4. 7
    5. }
    6. let skipped = if (false) {
    7. io.writeLine("unexpected")
    8. 9
    9. }
    10. io.writeLine("{taken}")
    11. io.writeLine("{skipped}")
    Ожидаемый выводКод завершения 0
    then
    ()
    ()
    
    $ topaz run example.tpz --compiler self · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

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

    A unit context accepts discarded non-unit branch values

    Ссылка
    example.tpzA unit context accepts discarded non-unit branch valuesОткрыть песочницу →
    1. let taken: () = if (true) { 7 }
    2. let skipped: () = if (false) { "discarded" }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    The inferred result can be assigned to unit

    Ссылка
    example.tpzThe inferred result can be assigned to unitОткрыть песочницу →
    1. let inferred = if (true) { 7 }
    2. let checked: () = inferred
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    An omitted else cannot produce an int result

    Ссылка
    example.tpzAn omitted else cannot produce an int resultОткрыть песочницу →
    1. let value: int = if (true) { 7 }
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      if-without-else-result-type-mismatch at example.tpz:1:18

    Evaluate a Map fallback when its key is absent

    Ссылка
    example.tpzEvaluate a Map fallback when its key is absentОткрыть песочницу →
    1. import std.io
    2. function makeMap() -> Map<string, int> {
    3. io.writeLine("map")
    4. map { "present": 7 }
    5. }
    6. function makeKey(name: string) -> string {
    7. io.writeLine("key")
    8. name
    9. }
    10. function makeDefault() -> int {
    11. io.writeLine("fallback")
    12. 99
    13. }
    14. let present = makeMap().get(makeKey("present")) ?? makeDefault()
    15. io.writeLine("present={present}")
    16. let absent = makeMap().get(makeKey("missing")) ?? makeDefault()
    17. io.writeLine("absent={absent}")
    18. let inner: Option<int> = None()
    19. let nested = map { "present": inner }
    20. let payload: Option<int> = nested.get("present") ?? Some(99)
    21. io.writeLine("inner={payload ?? 77}")
    Ожидаемый выводКод завершения 0
    map
    key
    present=7
    map
    key
    fallback
    absent=99
    inner=77
    
    $ topaz run example.tpz --compiler self · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    Ожидаемый стандартный вывод
    1. map
    2. key
    3. present=7
    4. map
    5. key
    6. fallback
    7. absent=99
    8. inner=77

    Preserve eager fallback effects with ordered bindings

    Ссылка
    example.tpzPreserve eager fallback effects with ordered bindingsОткрыть песочницу →
    1. import std.io
    2. function makeMap() -> Map<string, int> {
    3. io.writeLine("map")
    4. map { "present": 7 }
    5. }
    6. function makeKey(name: string) -> string {
    7. io.writeLine("key")
    8. name
    9. }
    10. function makeDefault() -> int {
    11. io.writeLine("fallback")
    12. 99
    13. }
    14. let receiver = makeMap()
    15. let key = makeKey("present")
    16. let default = makeDefault()
    17. let present = receiver.get(key) ?? default
    18. io.writeLine("present={present}")
    19. let absent = receiver.get("missing") ?? default
    20. io.writeLine("absent={absent}")
    Ожидаемый выводКод завершения 0
    map
    key
    fallback
    present=7
    absent=99
    
    $ topaz run example.tpz --compiler self · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    Ожидаемый стандартный вывод
    1. map
    2. key
    3. fallback
    4. present=7
    5. absent=99

    Use the empty structural type in aliases, parameters, and results

    Ссылка
    example.tpzUse the empty structural type in aliases, parameters, and resultsОткрыть песочницу →
    1. type Empty = {}
    2. function keep(value: Empty) -> {} { value }
    Ожидаемый выводКод завершения 0
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    An empty concurrent record passes through an explicit record signature

    Ссылка
    example.tpzAn empty concurrent record passes through an explicit record signatureОткрыть песочницу →
    1. import std.io
    2. function keep(value: {}) -> {} { value }
    3. let joined: {} = keep(concurrent {})
    4. io.writeLine("completed")
    Ожидаемый выводКод завершения 0
    completed
    
    $ topaz run example.tpz --compiler self · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

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

    The zero-field record is distinct from unit

    Ссылка
    example.tpzThe zero-field record is distinct from unitОткрыть песочницу →
    1. let joined: () = concurrent {}
    Ожидаемый выводНенулевой код завершения
    Нет стандартного вывода.
    $ topaz check example.tpz --compiler self --format json · Целевой продукт 5.21.3
    Ожидаемый результат

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

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

    • TPZ5001 →

      concurrent-empty-result-is-not-unit at example.tpz:1:18

    Pending

    Ссылка

    Related references

    Ссылка

    Bindings and scope →

    Functions and generics →

    Unexpected token →

    TPZ5022 →

    TPZ5001 →

    Type could not be inferred →

    Type alias cycle →

    Меню

    Загрузка →