Scope and ownership
링크This page owns declarations, parameter binding, calls, function type parameters, and return inference.
General type compatibility belongs to Types. Protocol conformance belongs to Protocols and implementations. Capture and mutation belong to Bindings and scope.
Declaration syntax
링크NamedFunction ="function" Identifier TypeParameters?"(" Parameters? ")" ("->" Type)? Block ;TypeParameters ="<" TypeParameter ("," TypeParameter)* ">" ;TypeParameter =Identifier (":" Identifier ("+" Identifier)*)? ;ParameterShape =FixedParameterShape | VariadicParameterShape ;FixedParameterShape =Identifier ":" Type ("=" Expression)? ;VariadicParameterShape ="..." Identifier ":" Type ;
A named function has a name, an optional type-parameter list, a parameter list, an optional return annotation, and a block body.
This syntax excerpt distinguishes fixed parameters, which may have defaults, from variadic parameters, which have no initializer. A variadic parameter must be final. Names are unique within each named-function or lambda parameter list. Type, Expression, and Block require their own productions.
This excerpt omits the special self form and does not establish its permitted declaration contexts. Receiver rules belong to Protocols and implementations.
Required fixed parameters come before defaulted fixed parameters. A final variadic parameter follows either sequence and has no default. Calls use positional values and explicit spread.
Unannotated self parameter
The parser also recognizes an unannotated first, nonvariadic parameter named self.
이유
A receiver gets its type from the enclosing implementation. A bare first self identifies that receiver without repeating the target type.
Lambda parameter lists
Every lambda has a parenthesized parameter list followed by => and an expression. Write () => expression for no parameters, (name) => expression for one, and (left, right) => expression for several. A parameter may include a type annotation. The bare form name => expression is rejected during parsing with TPZ2001.
Omitted lambda parameter types come from the expected function type or from inference. The parameter-context rules describe that typing behavior.
A lambda owns its return destination. Postfix ? follows lambda and callback propagation.
이유
A bare single parameter and a parenthesized single parameter introduce the same binding into the same lambda body. Parentheses preserve that intent and give lambdas the same parameter-list shape for every arity. Adding a parameter or an annotation does not require another syntax.
Parameters and default arguments
링크An ordinary parameter is written as name: Type. A variadic parameter places the ellipsis before its name.
Parameter bindings
Parameter bindings are immutable inside the function.
Collection arguments and the values reached through parameters follow collection value semantics.
이유
A parameter keeps the argument value bound at entry. Rebinding requires an explicit mutable local, as it does for other local names.
Variadic parameters
Inside the function, a variadic parameter annotated with T has type Array<T>.
이유
Packing the tail into Array<T> lets the body use the same indexing and iteration operations as any other array. When a call supplies no tail arguments, the body can inspect the empty array and select any replacement values. A variadic default would express that same choice in a second place.
Variadic parameter syntax fragment
링크...values: T
기대 결과
기대 결과
Syntax fragment; not a complete executable program.
The following is a syntax fragment. It is not passed to the CLI as a complete program.
Default arguments
A parameter can contain a default expression after =. The checker checks that expression against the parameter type and applies a constant-expression restriction. Failure of the constant-expression check produces TPZ5001.
TPZ5001 is also used for other conditions; this rule describes the confirmed constant-expression check.
이유
A supplied argument and its default must satisfy the same parameter type. Constant defaults make omission independent of runtime calls and parameter values.
Default evaluation and declaration scope
A default is evaluated whenever its argument is omitted. Supplied arguments are evaluated first. Missing defaults are then evaluated in parameter order. Default names resolve in the declaration environment, where the new parameters are unavailable. Defaults must be literals or const expressions. The admitted forms are parentheses, unary and binary expressions except in, untagged strings with constant interpolations, arrays and records without spread, and the checked numeric constant operations. Ordinary function calls and tagged templates do not satisfy this restriction.
A default must satisfy its parameter type and the constant-expression restrictions. Numeric constant operations include integer and, or, xor, and shift; float trunc, floor, ceil, and round; and the checked length constructors and conversions. The current identifier admission discrepancy is recorded as an implementation limitation.
이유
Declaration scope makes a default mean the same thing for every caller. Supplied arguments followed by omitted defaults give calls one evaluation order.
Parameter annotations, lambdas, and receivers
Named function parameters require a type annotation, with special syntax for a bare first self. Required fixed parameters precede defaulted fixed parameters. A later required parameter is rejected during parsing with TPZ2001. A final variadic parameter may follow the defaulted suffix. Lambda parameter annotations are optional. An omitted lambda type comes from the expected function parameter at that position, or becomes an inference variable when no context supplies it. A concrete nonvariadic function context also fixes the lambda’s parameter count. Parameters are immutable bindings. Receiver methods on own-module records, enums, and newtypes require bare self first, without a default or a variadic marker.
A receiver implementation targets a record, enum, or newtype declared in the same module. Generic targets use an explicit enclosing binder list, and each method may introduce ordinary function binders. The first bare self has the complete target type and has no annotation, default, or variadic marker. Protocol signatures use explicit annotated parameters and the same ordinary variadic/default rules.
이유
Required fixed parameters precede defaulted fixed parameters so every default can be selected by omitting a suffix. A named function supplies its own parameter types. A lambda can obtain them from the expected function type. Independent named settings remain expressible through a record parameter, whose field names preserve their roles without exposing local parameter names.
Variadic placement, defaults, and call arguments
A variadic parameter must be final and cannot have a default initializer. A variadic default is rejected during parsing with TPZ2001. Its element annotation T gives the parameter the body type Array<T>. An empty tail supplies an empty array. Required fixed parameters come before defaulted fixed parameters. Spread arguments require a variadic parameter and cannot fill fixed slots. Before a spread, every skipped fixed slot must already be supplied or have a default. Supply fixed overrides before the spread. Spread contents and subsequent positional values are appended to the variadic tail in source order.
Defaulted fixed parameters may precede the final variadic parameter. Supply a fixed override before a spread, as in total(1, ...tail). A spread cannot fill a required fixed slot. Positional arguments after a spread join the variadic tail. A variadic default initializer is a syntax error, even when the tail would be empty.
이유
A final variadic parameter gives each positional argument one destination. An absent tail consistently becomes an empty array without a second source of default values. An explicit array spread supplies the same ordered tail that a named tail argument would supply. Independent named settings keep their distinct configuration intent through record fields. When a call has no tail, the body can check its length and supply a replacement. Declaring a default tail would create a second spelling for the same intent as the empty tail.
Unique parameter names
Each parameter in a named function or lambda must have a distinct name within that parameter list. A repeated name is rejected with TPZ5008, whether or not the function is called. Separate parameter lists may reuse the same name.
이유
One parameter name identifies one body binding. Rejecting repeated names prevents later-name shadowing while positional slots remain distinct.
Required after default
링크function add(first: int = 1, second: int) -> int { first + second }
기대 결과
Type parameters and bounds
링크Declaring type parameters
Declare type parameters immediately after the function name. A type parameter can list protocol requirements using : and +, as in T: Show + JSON.
Protocol conformance and the operations made available by a bound are defined under Protocols and implementations.
Protocol signatures use these same method binders and bounds. Their call type-parameter list places implicit Self before the declared method parameters.
A type binder belongs to its lexical declaration. An implementation binder scopes over its target and methods; a method may add nested binders. Binder lists contain distinct names, and ordinary nested shadowing resolves to the inner declaration. Protocol matching compares those resolved identities after pairing method binders by position.
이유
Declaring type parameters with the function makes their scope visible. Bounds use the same <T: Protocol> notation as generic implementations.
Generic function declaration
링크function identity<T>(value: T) -> T {value}
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
관측한 단언 · 통과 · 5.21.3
종료 코드 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
표준 오류 출력 없음.
- 통과 · expected 0; observed 0
This is the complete declaration used by the generic-call examples.
Observed: The authored assertions passed. Recorded with Topaz 5.21.3 in run 42147883818 at 2026-. Document source: 1d6f9265d918.
Repeated protocol bounds
Each type parameter names a resolved protocol identity once. Repeating that identity produces TPZ5523, including through namespace qualification or aliases. A distinct protocol declaration remains a different requirement even when another module gives it the same name.
The duplicate-bound check is per type parameter and compares resolved protocol declarations. Namespace qualification, aliases, and whitespace do not create a second protocol identity.
이유
Repeating a protocol identity adds no capability. Resolve each bound before comparing it, so an alias or a space around a namespace dot cannot evade uniqueness. Distinct protocol declarations retain separate requirements even when their defining modules use the same spelling.
Locations and additional bound diagnostics
A resolved protocol identity may appear once for each type parameter. Aliases, namespace qualification, and whitespace preserve that identity. Each later occurrence produces TPZ5523 at the repeated bound. The same protocol may constrain another type parameter. Checking continues after reporting a repeated bound, so other applicable diagnostics may also appear.
이유
Reporting each repeated protocol identity points to the redundant requirement to remove. Source spelling must not change that result. Continuing the check lets independent mistakes be reported in the same run.
Bounds exposed by public callables
An exported function or a method signature of an exported protocol may expose built-in protocols and exported user protocols in its bounds. Resolve each bound through its defining protocol identity, including selected aliases and namespace qualification. A private protocol bound is rejected with TPZ5524. Default expressions keep their ordinary lexical environment. This visibility check concerns the public signature.
이유
A caller must be able to name every protocol contract exposed by a public callable. Visibility follows the resolved declaration identity, so user protocols can cross a module boundary by the same explicit export rule as other declarations. Renaming an import does not change whether that contract is public.
Compiler-owned type-parameter names
Topaz 6.0 rejects Length, Pt, Mm, Cm, In, Em as function type parameter names.
The compiler-owned type-parameter names are not a new list of globally reserved identifiers.
이유
Length and unit names identify built-in measurement types. Reserving them in type parameter lists prevents a generic binding from hiding those meanings.
An exported function may expose an exported user protocol bound
링크export protocol Labelled { function label(value: Self) -> string }export function describe<T: Labelled>(value: T) -> string { Labelled.label(value) }
표준 출력 없음.기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
Reject a public callable that exposes a private protocol bound
링크protocol Hidden { function label(value: Self) -> string }export function describe<T: Hidden>(value: T) -> string { Hidden.label(value) }
표준 출력 없음.기대 결과
Namespace qualification whitespace cannot repeat one protocol bound
링크import contracts as apifunction describe<T: api.Labelled + api . Labelled>(value: T) -> string { api.Labelled.label(value) }
표준 출력 없음.export protocol Labelled { function label(value: Self) -> string }
기대 결과
Equal protocol spellings in different modules keep different conformances
링크import std.io { writeLine }import first { Marked as First }import second { Marked as Second }import value { Item }function printBoth<T: First + Second>(value: T) -> () {writeLine(First.mark(value))writeLine(Second.mark(value))}printBoth(Item { text: "value" })
first value
second value
export record Item { text: string }
import value { Item }export protocol Marked { function mark(value: Self) -> string }impl Marked<Item> { function mark(value: Item) -> string { "first {value.text}" } }
import value { Item }export protocol Marked { function mark(value: Self) -> string }impl Marked<Item> { function mark(value: Item) -> string { "second {value.text}" } }
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
first valuesecond value
Return inference
링크Collecting an unannotated result
A named function may omit its - annotation syntactically. When the result is unannotated, the checker gathers explicit return types and the body's tail-expression type. A block that falls through without a tail expression contributes unit; an empty collected result also falls back to unit.
이유
Every return path contributes to the result type. Including fallthrough as unit prevents inference from promising a value on a path that returns none.
When inference needs an annotation
Confirmed TPZ5022 paths include an inferred result containing a generic projection without a nameable return type, and an unresolved result when the function calls a definition whose return type is still pending.
Omission does not guarantee successful inference. The identified pending-result case includes recursive or mutually recursive calls. An explicit result annotation is the indicated remedy for these paths. This does not mean every recursive function requires one.
An undetermined Result error type follows the Result annotation rule, using the same TPZ5022 diagnostic.
A lambda with an undetermined Result error type follows lambda and callback propagation and requires an annotation with TPZ5022.
이유
An explicit result gives recursive calls a type before their bodies are solved. It also supplies a named result where generic projection inference cannot.
Inferring a named function result
For a named function without a result annotation, collect every explicit return type and the body’s tail-expression type. A body that reaches its end without a tail contributes (). An empty collection also produces (). If a collected component is unresolved, the result remains unresolved. Otherwise, combine the collected types into a union and widen fresh scalar literal types. TPZ5022 requires an explicit annotation when the result contains an unnameable field or element type extracted from a generic value. It also requires one when an unresolved result depends on a function whose return type is still being inferred, including recursive dependencies.
The checker examines the final statement or tail to recognize a terminating block. An explicit return terminates; a block or parenthesized expression delegates to its contents; an if needs both branches to terminate; a match needs every arm to terminate. Partial type components are solved while joining, and fresh scalar literal results widen to their primitive types.
이유
Unioning returned types preserves all paths through the body. Widening fresh literals keeps the inferred signature independent of the particular literal returned.
Calling a function
링크Argument shapes
A call supplies positional expressions in parameter order. . expands an array into the variadic tail. Omitted trailing fixed arguments use their defaults. A name: expression argument is rejected during parsing with TPZ2001. Pass named settings as fields of an ordinary record argument. Field names associate values with settings, so reordering the fields cannot exchange their roles.
Pass named settings in an ordinary record argument. Field names keep each value attached to its setting when the fields are reordered.
이유
Named arguments and record fields can both identify which setting a value configures. A record preserves that intent as data while the call passes one positional value. Reordering fields cannot exchange the roles of two settings with the same type. Function types describe parameter positions, so this call convention also works for callbacks, methods, and constructors. Parameter names remain local bindings and can change without rewriting callers. Spread preserves the separate intent of supplying an ordered variadic tail.
Generic calls
Generic calls can infer type arguments or supply them explicitly after a name or member access. A <. sequence after a parenthesized expression is not a generic call. Parentheses preserve a named function’s declaration signature, so (identity)(value) can infer its type arguments. Write identity<Type>(value) to supply them explicitly.
이유
Topaz has one way to say each thing. Explicit type arguments have one place, directly after the name or member being called. A parenthesized callee already keeps the declaration it names, so a second spelling would add nothing. One position also keeps the lookahead that separates a call from a comparison simple. Explicit type arguments on a computed generic callable currently have little demonstrated use. This syntax can be revisited when a concrete program needs it.
Evaluation, binding, and type inference at a call
Evaluate the callee once, then evaluate supplied arguments once from left to right as written. Each positional argument fills the next fixed parameter until the variadic tail begins. A spread supplies the variadic tail and cannot fill an unsatisfied fixed parameter. Missing fixed arguments use their defaults, evaluated after supplied arguments in declaration order. Named call syntax is rejected with TPZ2001 during parsing. Explicit type arguments supply the complete declared list in order and must agree with both the arguments and the expected result. Each call starts fresh type inference. Later evidence cannot replace an already fixed type. Parentheses preserve a named function’s call signature. Lambda and generic-function callbacks receive the expected function type from their parameter slot.
Type inference may inspect independent arguments before a callback to learn its expected input types. This static dependency order does not change runtime evaluation order. The existing explicit-type-argument spacing limitation remains an implementation discrepancy.
For a call that previously used names, map each supplied value to the declaration position. Preserve effect order by evaluating expressions into fresh local bindings in their original order, then pass those bindings positionally. If a required parameter followed a defaulted one, move required parameters first and migrate every call against the new signature. Reordering parameters or adding required parameters changes the API. Adding a trailing defaulted fixed parameter preserves existing fixed-arity callers; inserting it before a variadic tail changes that tail and requires migration. Use an options record when independent optional settings must evolve. Parameter renaming alone does not change call sites.
이유
Each call gets fresh type variables so one use cannot constrain another. Evaluating the callee and each argument once makes effects predictable. A record argument preserves named configuration through its fields, so a function value can receive the same settings as a direct call.
Named form
링크function pick(value: int) -> int { value }pick(value: 3)
기대 결과
Positional defaults
링크import std.io { writeLine }function add(left: int, right: int = 2) -> int { left + right }let callback: (int, int) -> int = (left, right) => left + rightwriteLine("{add(3)}:{add(3, 4)}:{callback(3, 4)}")
5:7:7
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
5:7:7
Examples
링크Inferred and explicit type arguments
링크function identity<T>(value: T) -> T {value}let number: int = identity(3)let text: string = identity("Topaz")let explicit: int = identity<int>(1)
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
관측한 단언 · 통과 · 5.21.3
종료 코드 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
표준 오류 출력 없음.
- 통과 · expected 0; observed 0
Expected observation: checking accepts the program. Existing test source contains a related generic id<T> callback example. Its existence does not verify this exact program or every call context.
Observed: The authored assertions passed. Recorded with Topaz 5.21.3 in run 42147883818 at 2026-. Document source: 1d6f9265d918.
Repeated-bound example
링크function duplicate<T: Show + Show>(value: T) -> T {value}
기대 결과
TPZ5523 points to the second Show at example.. Each later occurrence for the same type parameter is diagnosed. Checking continues, so other applicable diagnostics may also appear. Remove the repeated bound to correct this program. The earlier receipt predates the location assertion; CI must execute this revision.
Observed: The authored exit and diagnostic-cause assertions passed. The primary-location assertion and additional-diagnostics policy remain pending. Recorded with Topaz 5.21.3 in run 42147883818 at 2026-. Document source: 1d6f9265d918.
Repeated bound removed
링크function duplicate<T: Show>(value: T) -> T {value}
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
관측한 단언 · 통과 · 5.21.3
종료 코드 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
표준 오류 출력 없음.
- 통과 · expected 0; observed 0
Acceptance of this corrected complete program is a separate check.
Observed: The authored assertions passed. Recorded with Topaz 5.21.3 in run 42147883818 at 2026-. Document source: 1d6f9265d918.
Adjacent explicit type argument
링크function identity<T>(value: T) -> T {value}let explicit: int = identity<int>(1)
example.tpz: types-ok (1 module)
example.tpz: resolve-ok (1 module)
기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
관측한 단언 · 통과 · 5.21.3
종료 코드 0.
example.tpz: types-ok (1 module)example.tpz: resolve-ok (1 module)
표준 오류 출력 없음.
- 통과 · expected 0; observed 0
The original comparison fragment is completed with the same identity declaration and an annotated result binding.
Observed: The authored assertions passed. Recorded with Topaz 5.21.3 in run 42147883818 at 2026-. Document source: 1d6f9265d918.
Spaced explicit type argument
링크function identity<T>(value: T) -> T {value}let explicit: int = identity<int> (1)
표준 출력 없음.error[TPZ5002]: `int` is not bound
--> example.tpz:5:30
|
5 | let explicit: int = identity<int> (1)
| ^^^
example.tpz: 1 type diagnostic
기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
관측한 단언 · 실패 · 5.21.3
종료 코드 1.
표준 출력 없음.
error[TPZ5002]: `int` is not bound--> example.tpz:5:30|5 | let explicit: int = identity<int> (1)| ^^^example.tpz: 1 type diagnostic
- 실패 · expected 0; observed 1
The expected language behavior is the same as the adjacent spelling. IL-001 remains an implementation limitation; rejection must not become a negative conformance rule.
Observed: The authored acceptance assertion failed. Recorded with Topaz 5.21.3 in run 42147883818 at 2026-. Document source: 1d6f9265d918.
A repeated protocol after a different bound
링크function repeated<T: Show + Eq + Show>(value: T) -> T { value }
기대 결과
The same protocol on different type parameters
링크function choose<T: Show, U: Show>(first: T, second: U) -> T { first }
기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
Omitted and supplied defaults
링크import std.io { writeLine }const base: int = 40function answer(value: int = base + 2) -> int { value }writeLine("{answer()}")writeLine("{answer(7)}")writeLine("{(answer)(9)}")
42
7
9
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
4279
An ordinary call is not a constant default
링크function compute() -> int { 42 }function answer(value: int = compute()) -> int { value }
기대 결과
A runtime binding is not a const default
링크let mut current: int = 1function answer(value: int = current) -> int { value }
기대 결과
The intended literal-or-const restriction requires rejection. SELF currently accepts an identifier in a default without testing its declaration kind. Keep this rejection expectation while the implementation discrepancy is reviewed.
Return values, tail values, and unit fallthrough
링크function choose(flag: bool) {if (flag) { return 1 }"other"}function maybe(flag: bool) {if (flag) { return 1 }}function empty() {}let choice: int | string = choose(false)let absence: int | () = maybe(false)let nothing: () = empty()
기대 결과
기대 결과
검사가 프로그램을 받아들입니다. 종료 코드 0.
An unresolved recursive result needs an annotation
링크function recur() { recur() }
기대 결과
An explicit result for recursive calls
링크import std.io { writeLine }function countDown(value: int) -> int {if (value == 0) { 0 } else { countDown(value - 1) }}writeLine("{countDown(3)}")
0
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
0
A destructured generic field cannot escape as an inferred result
링크function field<T>(value: T) {match (value) {case { x: x } => xcase _ => 0}}
기대 결과
Callee and arguments run once in source order
링크import std.io { writeLine }let mut trace: string = ""function combine(first: int, second: int) -> int { first + second }function pick() -> (int, int) -> int {trace += "c"combine}function mark(label: string, value: int) -> int {trace += labelvalue}let total = pick()(mark("a", 1), mark("b", 2))writeLine("{trace}:{total}")trace = ""let secondValue = mark("b", 2)let firstValue = mark("a", 1)let positional = combine(firstValue, secondValue)writeLine("{trace}:{positional}")
cab:3
ba:3
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
cab:3ba:3
Each call has its own type inference and callback context
링크import std.io { writeLine }function identity<T>(value: T) -> T { value }function apply<T, U>(value: T, step: (T) -> U) -> U { step(value) }let number: int = (identity)(3)let text: string = identity("ok")let stepped: int = apply(3, (value) => value + 1)let generic: int = apply(4, identity)writeLine("{number}")writeLine(text)writeLine("{stepped}")writeLine("{generic}")
3
ok
4
4
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
3ok44
Named call syntax is rejected before argument binding
링크function choose(first: int, second: int) -> int { first }choose(first: 1, first: 2, second: 3)
기대 결과
Named call syntax is rejected before argument binding
링크function choose(first: int, second: int) -> int { first }choose(first: 1, 2, second: 3)
기대 결과
Explicit type arguments must supply the full list
링크function choose<T, U>(first: T, second: U) -> T { first }choose<int>(1, "two")
기대 결과
A non-generic call has no type arguments
링크function identity(value: int) -> int { value }identity<int>(1)
기대 결과
A later argument cannot replace an inferred type
링크function same<T>(first: T, second: T) -> T { first }same(1, "two")
기대 결과
A required fixed parameter may follow a defaulted one
링크import std.io { writeLine }function add(second: int, first: int = 1) -> int { first + second }let step: (int) -> int = (value) => value + 1writeLine("{step(add(2))}")
4
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
4
An own-module nominal method uses a bare receiver
링크import std.io { writeLine }record Counter { value: int }impl Counter {function readValue(self) -> int { self.value }}writeLine("{Counter { value: 3 }.readValue()}")
3
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
3
Named value parameters need an annotation
링크function identity(value) -> int { 1 }
기대 결과
A contextual lambda must have the expected arity
링크let step: (int) -> int = (first, second) => first
기대 결과
A receiver method requires bare self
링크record Counter { value: int }impl Counter {function readValue(self: Counter) -> int { self.value }}
기대 결과
Fixed defaults and a variadic tail compose
링크import std.io { writeLine }function total(base: int = 10, ...values: int) -> int {let mut sum: int = basefor value in (values) { sum += value }sum}let tail: Array<int> = [2, 3]writeLine("{total()}")writeLine("{total(1, 2, 3)}")writeLine("{total(...tail)}")writeLine("{total(1, ...tail)}")writeLine("{total(1, ...tail, 4)}")
10
6
15
6
10
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
10615610
Spread cannot fill a required fixed parameter
링크function need(base: int, ...values: int) -> int { base }need(...[1, 2])
기대 결과
A spread cannot fill an unsatisfied required fixed slot. Supply a positional value before the spread, or give the fixed parameter a default.
A spread call requires a variadic parameter
링크function one(value: int) -> int { value }one(...[1])
기대 결과
Named call syntax is rejected before argument binding
링크function total(base: int = 10, ...values: int) -> int { base + values.length }total(base: 1, ...[2])
기대 결과
Named call syntax is rejected before argument binding
링크function total(base: int = 10, ...values: int) -> int { base + values.length }total(values: [1])
기대 결과
A variadic parameter before a fixed parameter
링크function misplaced(...values: int, last: int) -> int { last }
기대 결과
기대 결과
The final-parameter rule requires rejection. SELF has no placement-diagnostic producer, so the dedicated installed-CLI product test asserts a nonzero exit without assigning a diagnostic code.
This declaration must be rejected. The product check in node - keeps that nonzero-exit expectation. It is marked TODO for the recorded SELF placement-check limitation; its actual result must be reviewed in CI.
Multiple variadic parameters
링크function repeated(...first: int, ...second: int) -> () {}
기대 결과
기대 결과
The final-parameter rule requires rejection. SELF has no placement-diagnostic producer, so the dedicated installed-CLI product test asserts a nonzero exit without assigning a diagnostic code.
This declaration must be rejected. The product check in node - keeps that nonzero-exit expectation. It is marked TODO for the recorded SELF placement-check limitation; its actual result must be reviewed in CI.
Distinct parameter names in functions and lambdas
링크import std.io { writeLine }function add(left: int, right: int) -> int { left + right }let addLambda: (int, int) -> int = (left, right) => left + rightwriteLine("{add(1, 2)}")writeLine("{addLambda(3, 4)}")
3
7
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
37
A named function rejects a repeated parameter name
링크function choose(value: int, value: int) -> int { value }
기대 결과
기대 결과
거절 단계 check. 종료 코드가 0이 아닙니다.
bindings-local-same-scope-redeclaration at
example.tpz:1:29
A lambda rejects a repeated parameter name
링크let choose: (int, int) -> int = (value, value) => value
기대 결과
기대 결과
거절 단계 check. 종료 코드가 0이 아닙니다.
bindings-local-same-scope-redeclaration at
example.tpz:1:41
Separate parameter lists may reuse a name
링크import std.io { writeLine }function outer(value: int) -> int {let next: (int) -> int = (value) => value + 1next(value)}writeLine("{outer(4)}")
5
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
5
Empty and populated variadic tails without a default
링크import std.io { writeLine }function count(...values: int) -> int { values.length }let empty: Array<int> = []writeLine("{count()}")writeLine("{count(1, 2)}")writeLine("{count(...empty)}")
0
2
0
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
020
A variadic parameter rejects a default initializer
링크function count(...values: int = [1]) -> int { values.length }
기대 결과
A fixed default does not permit a variadic default
링크function count(base: int = 10, ...values: int = [1]) -> int { base + values.length }
기대 결과
A name accepts explicit type arguments
링크import std.io { writeLine }function identity<T>(value: T) -> T { value }let value: int = identity<int>(1)writeLine("{value}")
1
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
1
A member access accepts explicit type arguments
링크import std.io { writeLine }import helperslet value: int = helpers.identity<int>(2)writeLine("{value}")
2
export function identity<T>(value: T) -> T { value }
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
2
A parenthesized callee infers type arguments
링크import std.io { writeLine }function identity<T>(value: T) -> T { value }let value: int = (identity)(3)writeLine("{value}")
3
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
3
A parenthesized expression does not introduce explicit type arguments
링크function identity<T>(value: T) -> T { value }let value: int = (identity)<int>(1)
기대 결과
기대 결과
거절 단계 check. 종료 코드가 0이 아닙니다.
function-parenthesized-callee-type-argument at
example.tpz:2:29
After (identity), <int> is parsed as expression tokens. The name int is therefore a value read without a binding, which produces TPZ5002. Use identity<int>(1) for explicit type arguments or (identity)(1) for inference.
Parenthesized lambda parameter lists
링크import std.io { writeLine }let zero: () -> int = () => 0let one: (int) -> int = (value) => value + 1let typed: (int) -> int = (value: int) => value + 1let pair: (int, int) -> int = (left, right) => left + rightwriteLine("{zero()}")writeLine("{one(1)}")writeLine("{typed(2)}")writeLine("{pair(3, 4)}")
0
2
3
7
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
0237
A bare lambda parameter is rejected
링크let step: (int) -> int = value => value + 1
기대 결과
Record fields preserve settings when reordered
링크import std.io { writeLine }function dimensions(settings: { width: int, height: int }) -> string {"{settings.width}x{settings.height}"}let width = 80let height = 24let describe: ({ width: int, height: int }) -> string = dimensionswriteLine(dimensions({ width: width, height: height }))writeLine(dimensions({ height: height, width: width }))writeLine(describe({ height: height, width: width }))
80x24
80x24
80x24
기대 결과
기대 결과
실행을 마칩니다. 종료 코드 0.
80x2480x2480x24
Related diagnostics
링크The catalog owns causes, correction examples, and output details. This page owns the function rules.
Wrong number of explicit type arguments →