본문으로 건너뛰기
토파즈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. 종료 코드가 0이 아닙니다.

    관측한 단언 · 통과 · 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. 종료 코드가 0이 아닙니다.

    • 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. 종료 코드가 0이 아닙니다.

    • 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. 종료 코드가 0이 아닙니다.

    • 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
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    필수 기본 위치 계약은 미정입니다.

    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"
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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 }
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ 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. 종료 코드가 0이 아닙니다.

    • 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 }
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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 }
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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 {}
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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 {}
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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") } }
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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 }
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz --compiler self · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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 {}
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check example.tpz --compiler self --format json · 대상 제품 5.21.3
    기대 결과

    기대 결과

    거절 단계 check. 종료 코드가 0이 아닙니다.

    • 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 →

    메뉴

    다운로드 →