본문으로 건너뛰기
토파즈6.0 · 출시 전
다운로드 →

문서 검색

명세 6.0

방향키로 결과를 고르고 Enter를 눌러 여세요.

API 이름, 진단 번호, 규칙 또는 프로젝트 주제를 입력하세요.

    언어 · 12장 · 12개 규칙

    실패와 전파

    Read and check Result propagation and callable-local Result or Option propagation with postfix ?.

    Scope and ownership

    링크

    Use this chapter to inspect error propagation and locate incompatible operand or return types.

    This page owns postfix Result propagation and callable-local Result or Option propagation. Types owns general type compatibility. Pattern matching owns case syntax. Blocks and control flow owns explicit returns and cleanup ordering. Functions and generics owns return annotations and inference. Diagnostic entries own code-specific explanations. Command entries own process results.

    Propagation syntax

    링크
    EBNF
    1. Propagation = PostfixExpression "?" ;

    Expression precedence is specified by Expressions and operators.

    규칙topaz.rule.failure-and-propagation.postfix

    Postfix operand

    Postfix ? takes the preceding postfix expression as its operand.

    이유

    Postfix placement keeps the operation that may fail next to the point that forwards its error. It follows the binding order of calls and member access.

    Values and early return

    링크
    규칙topaz.rule.failure-and-propagation.evaluate-once

    Operand evaluation

    In a named function, ? evaluates its Result operand once.

    The corresponding lambda and callback behavior follows lambda and callback propagation.

    이유

    Repeated evaluation could repeat input, output, or mutation before deciding whether to return an error.

    규칙topaz.rule.failure-and-propagation.ok

    Successful operand

    When the operand produces Ok(value), ? yields value and evaluation continues in the enclosing named function.

    The corresponding lambda and callback behavior follows lambda and callback propagation.

    이유

    A successful operation supplies the value needed by later expressions without ending the function.

    규칙topaz.rule.failure-and-propagation.err

    Error return

    When the operand produces Err(error), ? returns that Result with its error payload from the enclosing named function. Subsequent expressions in its body are skipped.

    The corresponding lambda and callback behavior follows lambda and callback propagation.

    이유

    Preserving the error payload keeps failure information intact. Skipping the remaining body prevents later work from using a value that was not produced.

    규칙topaz.rule.failure-and-propagation.callback-propagation

    Propagation returns from the current callable

    Postfix ? in a lambda or callback targets that callable's own return. Each function boundary has one propagation destination. For a Result-returning lambda, an Ok yields its payload and an Err returns the original error Result from that invocation. In an Option-returning lambda, Some yields its payload and None returns None from that invocation. The remaining lambda body is skipped on either return. The surrounding function continues after the call and can propagate the returned value with its own ?.

    A lambda using ? must return Result or Option. Propagating a Result from a lambda returning another type uses the same TPZ5001 rejection as the named function return rule. The expected callback type still applies. A Result-returning lambda does not satisfy a bool callback slot such as filter. An undetermined Result error type requires an annotation with TPZ5022 under the error annotation rule.

    이유

    Each function boundary gives ? one return destination. A standard function such as map or filter can call a callback without handling nonlocal control transfer.

    규칙topaz.rule.failure-and-propagation.operand-fault

    Operand fault

    A runtime fault raised while evaluating the operand continues as a runtime fault.

    An ordinary runtime fault follows fault termination.

    A runtime fault remains a fault inside a lambda or callback. It is not a returned Err or None under lambda and callback propagation.

    이유

    A runtime fault interrupts evaluation, while an Err is an ordinary value. Keeping these paths distinct prevents propagation from silently converting a fault into a Result.

    Operand and return types

    링크
    규칙topaz.rule.failure-and-propagation.result-type

    Success type

    For an operand of type Result<T, E>, operand? has type T.

    이유

    Successful propagation supplies the payload to the next expression. Its type is the success type because the Result wrapper has been handled.

    규칙topaz.rule.failure-and-propagation.operand-required

    Result operand requirement

    In a named function returning Result, a propagation operand with a resolved non-Result type is rejected during checking with TPZ5001. Option-returning lambdas follow the callable propagation rule.

    Option-returning lambdas follow lambda and callback propagation.

    이유

    A Result return needs an error Result to forward. An Option operand supplies no error payload for that Result return.

    규칙topaz.rule.failure-and-propagation.function-context

    Enclosing function

    Using ? without an enclosing function return context is rejected during checking with TPZ5001.

    The corresponding lambda and callback behavior follows lambda and callback propagation.

    이유

    Propagation needs a function return target. Without one, the error has no destination.

    규칙topaz.rule.failure-and-propagation.result-return

    Result return requirement

    Propagating a Result from a function with a resolved non-Result return type is rejected during checking with TPZ5001.

    An undetermined Result error type follows the annotation requirement.

    The corresponding lambda and callback behavior follows lambda and callback propagation.

    이유

    The enclosing return type must admit the error Result that propagation returns. Otherwise the function could produce a value outside its declared type.

    규칙topaz.rule.failure-and-propagation.error-assignability

    Error type compatibility

    For an operand of type Result<T, E> in a function returning Result<U, F>, E must be assignable to F. Incompatible resolved error types produce TPZ5001 during checking. The propagation step does not compare T with U.

    이유

    An error can leave the function at this point, so it must fit the declared error type. The success payload remains local and can be transformed before return.

    규칙topaz.rule.failure-and-propagation.error-annotation

    Annotating an unresolved Result error type

    If the Result error type cannot be determined, checking rejects the expression with TPZ5022 and requires a type annotation. Inference does not substitute a broad fallback type. This is the same diagnostic as the return annotation requirement.

    This uses the same diagnostic as return annotation requirements. Lambda and callback propagation gives each lambda and callback its own return destination.

    The corresponding lambda and callback behavior follows lambda and callback propagation.

    이유

    Return inference and Result error inference use the same annotation rule and diagnostic. The program therefore has a determined error type before emission.

    Examples and counterexamples

    링크

    The checking examples pair rejected files with complete repairs. The execution example makes operand evaluation and continuation visible.

    Option operand

    링크
    example.tpzOption operand플레이그라운드 열기 →
    1. function advance(value: Option<int>) -> Result<int, string> {
    2. let number: int = value?
    3. Ok(number + 1)
    4. }
    기록된 출력종료 코드 1
    표준 출력 없음.
    error[TPZ5001]: `?` requires a Result value, found `Option<int>`
     --> example.tpz:2:23
      |
    2 |     let number: int = value?
      |                       ^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5001 →

      result-required-for-propagation at example.tpz:2:23

    관측한 단언 · 통과 · 5.21.3

    종료 코드 1.

    표준 출력 없음.

    관측한 표준 오류 출력
    1. error[TPZ5001]: `?` requires a Result value, found `Option<int>`
    2. --> example.tpz:2:23
    3. |
    4. 2 | let number: int = value?
    5. | ^^^^^^
    6. example.tpz: 1 type diagnostic
    • 통과 · expected nonzero; observed 1
    • 통과 · checking TPZ5001; cause result-required-for-propagation; primary location asserted; additional diagnostics allow
    • 통과 · stdout matches the authored expectation

    Result operand

    링크
    example.tpzResult operand플레이그라운드 열기 →
    1. function advance(value: Result<int, string>) -> Result<int, string> {
    2. let number: int = value?
    3. Ok(number + 1)
    4. }
    5. let success: Result<int, string> = advance(Ok(4))
    6. let failure: Result<int, string> = advance(Err("missing"))
    기록된 출력종료 코드 0
    표준 출력 없음.
    $ topaz check example.tpz --compiler self --format json · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

    검사가 프로그램을 받아들입니다. 종료 코드 0.

    관측한 단언 · 통과 · 5.21.3

    종료 코드 0.

    표준 출력 없음.

    표준 오류 출력 없음.

    • 통과 · expected 0; observed 0
    • 통과 · expected 0; observed 0
    • 통과 · stdout matches the authored expectation
    • 통과 · stderr matches the authored expectation

    Integer return type

    링크
    example.tpzInteger return type플레이그라운드 열기 →
    1. function read(value: Result<int, string>) -> int {
    2. value?
    3. }
    기록된 출력종료 코드 1
    표준 출력 없음.
    error[TPZ5001]: `?` propagates an error, but the function returns `int`, not a Result
     --> example.tpz:2:5
      |
    2 |     value?
      |     ^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5001 →

      propagation-requires-result-return at example.tpz:2:5

    관측한 단언 · 통과 · 5.21.3

    종료 코드 1.

    표준 출력 없음.

    관측한 표준 오류 출력
    1. error[TPZ5001]: `?` propagates an error, but the function returns `int`, not a Result
    2. --> example.tpz:2:5
    3. |
    4. 2 | value?
    5. | ^^^^^^
    6. example.tpz: 1 type diagnostic
    • 통과 · expected nonzero; observed 1
    • 통과 · checking TPZ5001; cause propagation-requires-result-return; primary location asserted; additional diagnostics allow
    • 통과 · stdout matches the authored expectation

    Result return type

    링크
    example.tpzResult return type플레이그라운드 열기 →
    1. function read(value: Result<int, string>) -> Result<int, string> {
    2. let number: int = value?
    3. Ok(number)
    4. }
    기록된 출력종료 코드 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

    Incompatible error types

    링크
    example.tpzIncompatible error types플레이그라운드 열기 →
    1. function relay(value: Result<int, string>) -> Result<int, int> {
    2. let number: int = value?
    3. Ok(number)
    4. }
    기록된 출력종료 코드 1
    표준 출력 없음.
    error[TPZ5001]: expected `int`, found `string`
     --> example.tpz:2:23
      |
    2 |     let number: int = value?
      |                       ^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5001 →

      propagated-error-type-not-assignable at example.tpz:2:23

    관측한 단언 · 통과 · 5.21.3

    종료 코드 1.

    표준 출력 없음.

    관측한 표준 오류 출력
    1. error[TPZ5001]: expected `int`, found `string`
    2. --> example.tpz:2:23
    3. |
    4. 2 | let number: int = value?
    5. | ^^^^^^
    6. example.tpz: 1 type diagnostic
    • 통과 · expected nonzero; observed 1
    • 통과 · checking TPZ5001; cause propagated-error-type-not-assignable; primary location asserted; additional diagnostics allow
    • 통과 · stdout matches the authored expectation

    Matching error types

    링크
    example.tpzMatching error types플레이그라운드 열기 →
    1. function relay(value: Result<int, string>) -> Result<int, string> {
    2. let number: int = value?
    3. Ok(number)
    4. }
    기록된 출력종료 코드 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

    Propagation at top level

    링크
    example.tpzPropagation at top level플레이그라운드 열기 →
    1. let value: Result<int, string> = Ok(1)
    2. let number: int = value?
    기록된 출력종료 코드 1
    표준 출력 없음.
    error[TPZ5001]: `return` outside a function
     --> example.tpz:2:19
      |
    2 | let number: int = value?
      |                   ^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5001 →

      propagation-outside-function at example.tpz:2:19

    관측한 단언 · 통과 · 5.21.3

    종료 코드 1.

    표준 출력 없음.

    관측한 표준 오류 출력
    1. error[TPZ5001]: `return` outside a function
    2. --> example.tpz:2:19
    3. |
    4. 2 | let number: int = value?
    5. | ^^^^^^
    6. example.tpz: 1 type diagnostic
    • 통과 · expected nonzero; observed 1
    • 통과 · checking TPZ5001; cause propagation-outside-function; primary location asserted; additional diagnostics allow
    • 통과 · stdout matches the authored expectation

    Observe success and early error return

    링크
    example.tpzObserve success and early error return플레이그라운드 열기 →
    1. import std.io
    2. function observe(value: Result<int, string>) -> Result<int, string> {
    3. io.writeLine("operand")
    4. value
    5. }
    6. function advance(value: Result<int, string>) -> Result<int, string> {
    7. let number: int = observe(value)?
    8. io.writeLine("continued")
    9. Ok(number + 1)
    10. }
    11. let success: Result<int, string> = advance(Ok(4))
    12. match (success) {
    13. case Ok(number) => io.writeLine("ok {number}")
    14. case Err(error) => io.writeLine("unexpected {error}")
    15. }
    16. let failure: Result<int, string> = advance(Err("missing"))
    17. match (failure) {
    18. case Ok(number) => io.writeLine("unexpected {number}")
    19. case Err(error) => io.writeLine("error {error}")
    20. }
    기록된 출력종료 코드 0
    operand
    continued
    ok 5
    operand
    error missing
    
    $ topaz run example.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

    실행을 마칩니다. 종료 코드 0.

    기대 표준 출력
    1. operand
    2. continued
    3. ok 5
    4. operand
    5. error missing
    관측한 단언 · 통과 · 5.21.3

    종료 코드 0.

    관측한 표준 출력
    1. operand
    2. continued
    3. ok 5
    4. operand
    5. error missing

    표준 오류 출력 없음.

    • 통과 · expected 0; observed 0
    • 통과 · stdout matches the authored expectation
    • 통과 · stdout matches the authored expectation
    • 통과 · stdout matches the authored expectation
    • 통과 · stderr matches the authored expectation

    An unknown Result error type requires an annotation

    링크
    main.tpzAn unknown Result error type requires an annotation플레이그라운드 열기 →
    1. function value() { Ok(1) }
    2. let result = value()
    기대 출력0이 아닌 종료 코드
    표준 출력 없음.
    $ topaz check main.tpz --compiler self · 대상 제품 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5022 →

      result-error-annotation-required at main.tpz:1:10

    A Result return annotation fixes the error type

    링크
    main.tpzA Result return annotation fixes the error type플레이그라운드 열기 →
    1. import std.io
    2. function value() -> Result<int, string> { Ok(1) }
    3. let result = match (value()) {
    4. case Ok(number) => number
    5. case Err(_) => 0
    6. }
    7. io.writeLine("{result}")
    기대 출력종료 코드 0
    1
    
    $ topaz run main.tpz --compiler self · 대상 제품 5.21.3
    기대 결과

    기대 결과

    실행을 마칩니다. 종료 코드 0.

    기대 표준 출력
    1. 1

    Mapping a propagating lambda produces an array of Results

    링크
    main.tpzMapping a propagating lambda produces an array of Results플레이그라운드 열기 →
    1. import std.io
    2. function surrounding() -> int {
    3. let inputs: Array<Result<int, string>> = [Ok(1), Err("stop"), Ok(3)]
    4. let advance: (Result<int, string>) -> Result<int, string> = (value) => {
    5. let number = value?
    6. io.writeLine("lambda {number}")
    7. Ok(number + 1)
    8. }
    9. let results: Array<Result<int, string>> = inputs.map(advance)
    10. io.writeLine("after map")
    11. for result in (results) {
    12. match (result) {
    13. case Ok(number) => io.writeLine("ok {number}")
    14. case Err(error) => io.writeLine("err {error}")
    15. }
    16. }
    17. 7
    18. }
    19. io.writeLine("{surrounding()}")
    기록된 출력종료 코드 0
    lambda 1
    lambda 3
    after map
    ok 2
    err stop
    ok 4
    7
    
    $ topaz run main.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

    실행을 마칩니다. 종료 코드 0.

    기대 표준 출력
    1. lambda 1
    2. lambda 3
    3. after map
    4. ok 2
    5. err stop
    6. ok 4
    7. 7
    관측한 단언 · 통과 · 5.21.3

    종료 코드 0.

    관측한 표준 출력
    1. lambda 1
    2. lambda 3
    3. after map
    4. ok 2
    5. err stop
    6. ok 4
    7. 7

    표준 오류 출력 없음.

    • 통과 · expected 0; observed 0
    • 통과 · stdout matches the authored expectation
    • 통과 · stderr matches the authored expectation

    None returns from its lambda while the caller continues

    링크
    main.tpzNone returns from its lambda while the caller continues플레이그라운드 열기 →
    1. import std.io
    2. let advance: (Option<int>) -> Option<int> = (value) => {
    3. let number = value?
    4. io.writeLine("some {number}")
    5. Some(number + 1)
    6. }
    7. let missing = advance(None())
    8. io.writeLine("after none")
    9. match (missing) {
    10. case Some(number) => io.writeLine("{number}")
    11. case None() => io.writeLine("none")
    12. }
    13. let present = advance(Some(2))
    14. match (present) {
    15. case Some(number) => io.writeLine("{number}")
    16. case None() => io.writeLine("none")
    17. }
    기록된 출력종료 코드 1
    표준 출력 없음.
    error[TPZ5001]: `?` requires a Result value, found `Option<int>`
     --> main.tpz:3:18
      |
    3 |     let number = value?
      |                  ^^^^^^
    
    main.tpz: 1 type diagnostic
    
    $ topaz run main.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

    실행을 마칩니다. 종료 코드 0.

    기대 표준 출력
    1. after none
    2. none
    3. some 2
    4. 3
    관측한 단언 · 실패 · 5.21.3

    종료 코드 1.

    표준 출력 없음.

    관측한 표준 오류 출력
    1. error[TPZ5001]: `?` requires a Result value, found `Option<int>`
    2. --> main.tpz:3:18
    3. |
    4. 3 | let number = value?
    5. | ^^^^^^
    6. main.tpz: 1 type diagnostic
    • 실패 · expected 0; observed 1
    • 실패 · stdout matches the authored expectation
    • 실패 · stderr matches the authored expectation

    An integer-returning lambda cannot propagate a Result

    링크
    main.tpzAn integer-returning lambda cannot propagate a Result플레이그라운드 열기 →
    1. let read: (Result<int, string>) -> int = (value) => {
    2. value?
    3. }
    기록된 출력종료 코드 1
    표준 출력 없음.
    error[TPZ5001]: `?` propagates an error, but the function returns `int`, not a Result
     --> main.tpz:2:5
      |
    2 |     value?
      |     ^^^^^^
    
    main.tpz: 1 type diagnostic
    
    $ topaz check main.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5001 →

      propagation-requires-result-return at main.tpz:2:5

    관측한 단언 · 통과 · 5.21.3

    종료 코드 1.

    표준 출력 없음.

    관측한 표준 오류 출력
    1. error[TPZ5001]: `?` propagates an error, but the function returns `int`, not a Result
    2. --> main.tpz:2:5
    3. |
    4. 2 | value?
    5. | ^^^^^^
    6. main.tpz: 1 type diagnostic
    • 통과 · expected nonzero; observed 1
    • 통과 · stdout matches the authored expectation
    • 통과 · checking TPZ5001; cause propagation-requires-result-return; primary location asserted; additional diagnostics allow

    A propagating lambda needs a determined Result error type

    링크
    main.tpzA propagating lambda needs a determined Result error type플레이그라운드 열기 →
    1. let lift = () => {
    2. let value = Ok(1)?
    3. Ok(value)
    4. }
    기록된 출력종료 코드 0
    main.tpz: types-ok (1 module)
    main.tpz: resolve-ok (1 module)
    
    $ topaz check main.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5022 →

      result-error-annotation-required at main.tpz:1:12

    관측한 단언 · 실패 · 5.21.3

    종료 코드 0.

    관측한 표준 출력
    1. main.tpz: types-ok (1 module)
    2. main.tpz: resolve-ok (1 module)

    표준 오류 출력 없음.

    • 실패 · expected nonzero; observed 0
    • 실패 · stdout matches the authored expectation
    • 실패 · checking TPZ5022; cause result-error-annotation-required; primary location asserted; additional diagnostics allow

    Filter rejects a Result-returning callback where bool is required

    링크
    main.tpzFilter rejects a Result-returning callback where bool is required플레이그라운드 열기 →
    1. let predicate: (Result<int, string>) -> Result<bool, string> = (value) => {
    2. let number = value?
    3. Ok(number > 0)
    4. }
    5. let inputs: Array<Result<int, string>> = [Ok(1)]
    6. let selected = inputs.filter(predicate)
    기록된 출력종료 코드 1
    표준 출력 없음.
    error[TPZ5001]: expected `(Result<int, string>) -> bool`, found `(Result<int, string>) -> Result<bool, string>`
     --> main.tpz:6:30
      |
    6 | let selected = inputs.filter(predicate)
      |                              ^^^^^^^^^
    
    main.tpz: 1 type diagnostic
    
    $ topaz check main.tpz --compiler self · 기록에 사용한 토파즈 5.21.3
    기대 결과

    기대 결과

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

    • TPZ5001 →

      callback-return-type-mismatch at main.tpz:6:30

    관측한 단언 · 통과 · 5.21.3

    종료 코드 1.

    표준 출력 없음.

    관측한 표준 오류 출력
    1. error[TPZ5001]: expected `(Result<int, string>) -> bool`, found `(Result<int, string>) -> Result<bool, string>`
    2. --> main.tpz:6:30
    3. |
    4. 6 | let selected = inputs.filter(predicate)
    5. | ^^^^^^^^^
    6. main.tpz: 1 type diagnostic
    • 통과 · expected nonzero; observed 1
    • 통과 · stdout matches the authored expectation
    • 통과 · checking TPZ5001; cause callback-return-type-mismatch; primary location asserted; additional diagnostics allow

    Pending contracts

    링크

    Related references

    링크

    TPZ5001 →

    Functions and generics →

    check →

    TPZ5022 →

    메뉴

    다운로드 →