Skip to content
Topaz6.0 · Before release
Download

Search documentation

Specification 6.0 · Not released · Tested product 5.21.3

Use arrow keys to choose a result. Press Enter to open.

Type an API name, diagnostic number, rule, or project topic.

    Language · chapter 06 · 20 rules

    Functions and generics

    Functions relate parameter types, a body, and a result type. A named function can declare type parameters and require protocol bounds.

    Scope and ownership

    Link

    Edition: Topaz 5.21 language mode.

    Authority: the SELF compiler at source revision d61f9fd0efb0c358d382203ebe0cc0a1e187670a.

    Status: reference draft. The rules below have source evidence. Pending contracts remain publication blockers for a complete reference page.

    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

    Link
    EBNF
    1. NamedFunction =
    2. "function" Identifier TypeParameters?
    3. "(" Parameters? ")" ("->" Type)? Block ;
    4. TypeParameters =
    5. "<" TypeParameter ("," TypeParameter)* ">" ;
    6. TypeParameter =
    7. Identifier (":" Identifier ("+" Identifier)*)? ;
    8. ParameterShape =
    9. FixedParameterShape | VariadicParameterShape ;
    10. FixedParameterShape =
    11. Identifier ":" Type ("=" Expression)? ;
    12. VariadicParameterShape =
    13. "..." 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.

    Source evidence
    Ruletopaz.rule.function.parameter.self-recognition

    Unannotated self parameter

    The parser also recognizes an unannotated first, nonvariadic parameter named self.

    Why

    A receiver gets its type from the enclosing implementation. A bare first self identifies that receiver without repeating the target type.

    Source evidence
    Ruletopaz.rule.function.lambda.single-parameter

    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.

    Why

    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.

    Source evidence

    Parameters and default arguments

    Link

    An ordinary parameter is written as name: Type. A variadic parameter places the ellipsis before its name.

    Ruletopaz.rule.function.parameter.immutable

    Parameter bindings

    Parameter bindings are immutable inside the function.

    Collection arguments and the values reached through parameters follow collection value semantics.

    Why

    A parameter keeps the argument value bound at entry. Rebinding requires an explicit mutable local, as it does for other local names.

    Source evidence
    Ruletopaz.rule.function.parameter.variadic

    Variadic parameters

    Inside the function, a variadic parameter annotated with T has type Array<T>.

    Why

    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.

    Source evidence

    Variadic parameter syntax fragment

    Link
    example.tpzVariadic parameter syntax fragmentOpen in Playground
    1. ...values: T
    target product 5.21.3
    Expected result

    Expected result

    Syntax fragment; not a complete executable program.

    The following is a syntax fragment. It is not passed to the CLI as a complete program.

    Source evidence
    Ruletopaz.rule.function.parameter.default

    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.

    Why

    A supplied argument and its default must satisfy the same parameter type. Constant defaults make omission independent of runtime calls and parameter values.

    Source evidence
    Ruletopaz.rule.function.default-evaluation

    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.

    Why

    Declaration scope makes a default mean the same thing for every caller. Supplied arguments followed by omitted defaults give calls one evaluation order.

    Source evidence
    Ruletopaz.rule.function.parameter-contexts

    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.

    Why

    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.

    Source evidence
    Ruletopaz.rule.function.variadic-interactions

    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.

    Why

    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.

    Source evidence
    Ruletopaz.rule.function.parameter.unique-names

    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.

    Why

    One parameter name identifies one body binding. Rejecting repeated names prevents later-name shadowing while positional slots remain distinct.

    Source evidence

    Required after default

    Link
    example.tpzRequired after defaultOpen in Playground
    1. function add(first: int = 1, second: int) -> int { first + second }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-required-after-default at example.tpz:1:41
    Source evidence

    Type parameters and bounds

    Link
    Ruletopaz.rule.function.type-parameter.declaration

    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.

    Why

    Declaring type parameters with the function makes their scope visible. Bounds use the same <T: Protocol> notation as generic implementations.

    Source evidence

    Generic function declaration

    Link
    example.tpzGeneric function declaration
    1. function identity<T>(value: T) -> T {
    2. value
    3. }
    Recorded outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    No stderr.

    • Passed · 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-11-06T02:04:56.4183898Z. Document source: 1d6f9265d918.

    Source evidence
    Ruletopaz.rule.function.bound.unique

    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.

    Why

    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.

    Source evidence
    Ruletopaz.rule.function.bound.diagnostic-policy

    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.

    Why

    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.

    Source evidence
    Ruletopaz.rule.function.bound.exported

    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.

    Why

    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.

    Source evidence

    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.

    Why

    Length and unit names identify built-in measurement types. Reserving them in type parameter lists prevents a generic binding from hiding those meanings.

    Source evidence

    An exported function may expose an exported user protocol bound

    Link
    example.tpzAn exported function may expose an exported user protocol boundOpen in Playground
    1. export protocol Labelled { function label(value: Self) -> string }
    2. export function describe<T: Labelled>(value: T) -> string { Labelled.label(value) }
    Expected outputexit 0
    No stdout.
    $ topaz check example.tpz --format json · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Source evidence

    Reject a public callable that exposes a private protocol bound

    Link
    example.tpzReject a public callable that exposes a private protocol boundOpen in Playground
    1. protocol Hidden { function label(value: Self) -> string }
    2. export function describe<T: Hidden>(value: T) -> string { Hidden.label(value) }
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5524 protocol-private-public-bound at example.tpz:2:29
    Source evidence

    Namespace qualification whitespace cannot repeat one protocol bound

    Link
    example.tpzNamespace qualification whitespace cannot repeat one protocol boundOpen in Playground
    1. import contracts as api
    2. function describe<T: api.Labelled + api . Labelled>(value: T) -> string { api.Labelled.label(value) }
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz --format json · target product 5.21.3
    contracts.tpzNamespace qualification whitespace cannot repeat one protocol boundOpen in Playground
    1. export protocol Labelled { function label(value: Self) -> string }
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5523 protocol-repeated-resolved-bound at example.tpz:2:37
    Source evidence

    Equal protocol spellings in different modules keep different conformances

    Link
    example.tpzEqual protocol spellings in different modules keep different conformancesOpen in Playground
    1. import std.io { writeLine }
    2. import first { Marked as First }
    3. import second { Marked as Second }
    4. import value { Item }
    5. function printBoth<T: First + Second>(value: T) -> () {
    6. writeLine(First.mark(value))
    7. writeLine(Second.mark(value))
    8. }
    9. printBoth(Item { text: "value" })
    Expected outputexit 0
    first value
    second value
    
    $ topaz run example.tpz · target product 5.21.3
    value.tpzEqual protocol spellings in different modules keep different conformancesOpen in Playground
    1. export record Item { text: string }
    first.tpzEqual protocol spellings in different modules keep different conformancesOpen in Playground
    1. import value { Item }
    2. export protocol Marked { function mark(value: Self) -> string }
    3. impl Marked<Item> { function mark(value: Item) -> string { "first {value.text}" } }
    second.tpzEqual protocol spellings in different modules keep different conformancesOpen in Playground
    1. import value { Item }
    2. export protocol Marked { function mark(value: Self) -> string }
    3. impl Marked<Item> { function mark(value: Item) -> string { "second {value.text}" } }
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. first value
    2. second value
    Source evidence

    Return inference

    Link
    Ruletopaz.rule.function.return.collection

    Collecting an unannotated result

    A named function may omit its -> Type 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.

    Why

    Every return path contributes to the result type. Including fallthrough as unit prevents inference from promising a value on a path that returns none.

    Source evidence
    Ruletopaz.rule.function.return.annotation-required

    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.

    Why

    An explicit result gives recursive calls a type before their bodies are solved. It also supplies a named result where generic projection inference cannot.

    Source evidence
    Ruletopaz.rule.function.return-algorithm

    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.

    Why

    Unioning returned types preserves all paths through the body. Widening fresh literals keeps the inferred signature independent of the particular literal returned.

    Source evidence

    Calling a function

    Link
    Ruletopaz.rule.function.call.argument-shapes

    Argument shapes

    A call supplies positional expressions in parameter order. ...expression 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.

    Why

    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.

    Source evidence
    Ruletopaz.rule.function.call.type-arguments

    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.

    Why

    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.

    Source evidence
    Ruletopaz.rule.function.call-contract

    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.

    Why

    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.

    Source evidence

    Named form

    Link
    example.tpzNamed formOpen in Playground
    1. function pick(value: int) -> int { value }
    2. pick(value: 3)
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-named-call-syntax at example.tpz:2:11
    Source evidence

    Positional defaults

    Link
    example.tpzPositional defaults
    1. import std.io { writeLine }
    2. function add(left: int, right: int = 2) -> int { left + right }
    3. let callback: (int, int) -> int = (left, right) => left + right
    4. writeLine("{add(3)}:{add(3, 4)}:{callback(3, 4)}")
    Expected outputexit 0
    5:7:7
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 5:7:7
    Source evidence

    Examples

    Link

    Inferred and explicit type arguments

    Link
    example.tpzInferred and explicit type arguments
    1. function identity<T>(value: T) -> T {
    2. value
    3. }
    4. let number: int = identity(3)
    5. let text: string = identity("Topaz")
    6. let explicit: int = identity<int>(1)
    Recorded outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    No stderr.

    • Passed · 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-11-06T02:04:56.4645284Z. Document source: 1d6f9265d918.

    Source evidence

    Repeated-bound example

    Link
    example.tpzRepeated-bound exampleOpen in Playground
    1. function duplicate<T: Show + Show>(value: T) -> T {
    2. value
    3. }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5523 repeated-protocol-bound at example.tpz:1:30

    TPZ5523 points to the second Show at example.tpz:1:30. 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-11-06T02:04:56.5052224Z. Document source: 1d6f9265d918.

    Source evidence

    Repeated bound removed

    Link
    example.tpzRepeated bound removed
    1. function duplicate<T: Show>(value: T) -> T {
    2. value
    3. }
    Recorded outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    No stderr.

    • Passed · 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-11-06T02:04:56.5498911Z. Document source: 1d6f9265d918.

    Source evidence

    Adjacent explicit type argument

    Link
    example.tpzAdjacent explicit type argument
    1. function identity<T>(value: T) -> T {
    2. value
    3. }
    4. let explicit: int = identity<int>(1)
    Recorded outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    No stderr.

    • Passed · 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-11-06T02:04:56.5942732Z. Document source: 1d6f9265d918.

    Source evidence

    Spaced explicit type argument

    Link
    example.tpzSpaced explicit type argument
    1. function identity<T>(value: T) -> T {
    2. value
    3. }
    4. let explicit: int = identity<int> (1)
    Recorded outputexit 1
    No stdout.
    error[TPZ5002]: `int` is not bound
     --> example.tpz:5:30
      |
    5 | let explicit: int = identity<int> (1)
      |                              ^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · failed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ5002]: `int` is not bound
    2. --> example.tpz:5:30
    3. |
    4. 5 | let explicit: int = identity<int> (1)
    5. | ^^^
    6. example.tpz: 1 type diagnostic
    • Failed · 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-11-06T02:04:56.6394002Z. Document source: 1d6f9265d918.

    Source evidence

    A repeated protocol after a different bound

    Link
    example.tpzA repeated protocol after a different boundOpen in Playground
    1. function repeated<T: Show + Eq + Show>(value: T) -> T { value }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5523 repeated-protocol-bound at example.tpz:1:34
    Source evidence

    The same protocol on different type parameters

    Link
    example.tpzThe same protocol on different type parameters
    1. function choose<T: Show, U: Show>(first: T, second: U) -> T { first }
    Expected outputexit 0
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Source evidence

    Omitted and supplied defaults

    Link
    example.tpzOmitted and supplied defaults
    1. import std.io { writeLine }
    2. const base: int = 40
    3. function answer(value: int = base + 2) -> int { value }
    4. writeLine("{answer()}")
    5. writeLine("{answer(7)}")
    6. writeLine("{(answer)(9)}")
    Expected outputexit 0
    42
    7
    9
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 42
    2. 7
    3. 9
    Source evidence

    An ordinary call is not a constant default

    Link
    example.tpzAn ordinary call is not a constant defaultOpen in Playground
    1. function compute() -> int { 42 }
    2. function answer(value: int = compute()) -> int { value }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 function-default-constant-expression at example.tpz:2:30
    Source evidence

    A runtime binding is not a const default

    Link
    example.tpzA runtime binding is not a const defaultOpen in Playground
    1. let mut current: int = 1
    2. function answer(value: int = current) -> int { value }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 function-default-constant-expression at example.tpz:2:30

    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.

    Source evidence

    Return values, tail values, and unit fallthrough

    Link
    example.tpzReturn values, tail values, and unit fallthrough
    1. function choose(flag: bool) {
    2. if (flag) { return 1 }
    3. "other"
    4. }
    5. function maybe(flag: bool) {
    6. if (flag) { return 1 }
    7. }
    8. function empty() {}
    9. let choice: int | string = choose(false)
    10. let absence: int | () = maybe(false)
    11. let nothing: () = empty()
    Expected outputexit 0
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Source evidence

    An unresolved recursive result needs an annotation

    Link
    example.tpzAn unresolved recursive result needs an annotationOpen in Playground
    1. function recur() { recur() }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5022 function-unresolved-recursive-return at example.tpz:1:10
    Source evidence

    An explicit result for recursive calls

    Link
    example.tpzAn explicit result for recursive calls
    1. import std.io { writeLine }
    2. function countDown(value: int) -> int {
    3. if (value == 0) { 0 } else { countDown(value - 1) }
    4. }
    5. writeLine("{countDown(3)}")
    Expected outputexit 0
    0
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 0
    Source evidence

    A destructured generic field cannot escape as an inferred result

    Link
    example.tpzA destructured generic field cannot escape as an inferred resultOpen in Playground
    1. function field<T>(value: T) {
    2. match (value) {
    3. case { x: x } => x
    4. case _ => 0
    5. }
    6. }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5022 function-unnameable-projection-return at example.tpz:1:10
    Source evidence

    Callee and arguments run once in source order

    Link
    example.tpzCallee and arguments run once in source order
    1. import std.io { writeLine }
    2. let mut trace: string = ""
    3. function combine(first: int, second: int) -> int { first + second }
    4. function pick() -> (int, int) -> int {
    5. trace += "c"
    6. combine
    7. }
    8. function mark(label: string, value: int) -> int {
    9. trace += label
    10. value
    11. }
    12. let total = pick()(mark("a", 1), mark("b", 2))
    13. writeLine("{trace}:{total}")
    14. trace = ""
    15. let secondValue = mark("b", 2)
    16. let firstValue = mark("a", 1)
    17. let positional = combine(firstValue, secondValue)
    18. writeLine("{trace}:{positional}")
    Expected outputexit 0
    cab:3
    ba:3
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. cab:3
    2. ba:3
    Source evidence

    Each call has its own type inference and callback context

    Link
    example.tpzEach call has its own type inference and callback context
    1. import std.io { writeLine }
    2. function identity<T>(value: T) -> T { value }
    3. function apply<T, U>(value: T, step: (T) -> U) -> U { step(value) }
    4. let number: int = (identity)(3)
    5. let text: string = identity("ok")
    6. let stepped: int = apply(3, (value) => value + 1)
    7. let generic: int = apply(4, identity)
    8. writeLine("{number}")
    9. writeLine(text)
    10. writeLine("{stepped}")
    11. writeLine("{generic}")
    Expected outputexit 0
    3
    ok
    4
    4
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 3
    2. ok
    3. 4
    4. 4
    Source evidence

    Named call syntax is rejected before argument binding

    Link
    example.tpzNamed call syntax is rejected before argument bindingOpen in Playground
    1. function choose(first: int, second: int) -> int { first }
    2. choose(first: 1, first: 2, second: 3)
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-named-call-syntax at example.tpz:2:13
    Source evidence

    Named call syntax is rejected before argument binding

    Link
    example.tpzNamed call syntax is rejected before argument bindingOpen in Playground
    1. function choose(first: int, second: int) -> int { first }
    2. choose(first: 1, 2, second: 3)
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-named-call-syntax at example.tpz:2:13
    Source evidence

    Explicit type arguments must supply the full list

    Link
    example.tpzExplicit type arguments must supply the full listOpen in Playground
    1. function choose<T, U>(first: T, second: U) -> T { first }
    2. choose<int>(1, "two")
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5510 function-type-argument-count at example.tpz:2:1
    Source evidence

    A non-generic call has no type arguments

    Link
    example.tpzA non-generic call has no type argumentsOpen in Playground
    1. function identity(value: int) -> int { value }
    2. identity<int>(1)
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5512 function-non-generic-type-arguments at example.tpz:2:1
    Source evidence

    A later argument cannot replace an inferred type

    Link
    example.tpzA later argument cannot replace an inferred typeOpen in Playground
    1. function same<T>(first: T, second: T) -> T { first }
    2. same(1, "two")
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 function-conflicting-inference at example.tpz:2:9
    Source evidence

    A required fixed parameter may follow a defaulted one

    Link
    example.tpzA required fixed parameter may follow a defaulted one
    1. import std.io { writeLine }
    2. function add(second: int, first: int = 1) -> int { first + second }
    3. let step: (int) -> int = (value) => value + 1
    4. writeLine("{step(add(2))}")
    Expected outputexit 0
    4
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 4
    Source evidence

    An own-module nominal method uses a bare receiver

    Link
    example.tpzAn own-module nominal method uses a bare receiver
    1. import std.io { writeLine }
    2. record Counter { value: int }
    3. impl Counter {
    4. function readValue(self) -> int { self.value }
    5. }
    6. writeLine("{Counter { value: 3 }.readValue()}")
    Expected outputexit 0
    3
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 3
    Source evidence

    Named value parameters need an annotation

    Link
    example.tpzNamed value parameters need an annotationOpen in Playground
    1. function identity(value) -> int { 1 }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-parameter-annotation at example.tpz:1:24
    Source evidence

    A contextual lambda must have the expected arity

    Link
    example.tpzA contextual lambda must have the expected arityOpen in Playground
    1. let step: (int) -> int = (first, second) => first
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5004 function-lambda-arity at example.tpz:1:26
    Source evidence

    A receiver method requires bare self

    Link
    example.tpzA receiver method requires bare selfOpen in Playground
    1. record Counter { value: int }
    2. impl Counter {
    3. function readValue(self: Counter) -> int { self.value }
    4. }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5022 function-bare-receiver at example.tpz:3:24
    Source evidence

    Fixed defaults and a variadic tail compose

    Link
    example.tpzFixed defaults and a variadic tail compose
    1. import std.io { writeLine }
    2. function total(base: int = 10, ...values: int) -> int {
    3. let mut sum: int = base
    4. for value in (values) { sum += value }
    5. sum
    6. }
    7. let tail: Array<int> = [2, 3]
    8. writeLine("{total()}")
    9. writeLine("{total(1, 2, 3)}")
    10. writeLine("{total(...tail)}")
    11. writeLine("{total(1, ...tail)}")
    12. writeLine("{total(1, ...tail, 4)}")
    Expected outputexit 0
    10
    6
    15
    6
    10
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 10
    2. 6
    3. 15
    4. 6
    5. 10
    Source evidence

    Spread cannot fill a required fixed parameter

    Link
    example.tpzSpread cannot fill a required fixed parameterOpen in Playground
    1. function need(base: int, ...values: int) -> int { base }
    2. need(...[1, 2])
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5004 function-spread-skips-fixed at example.tpz:2:9

    A spread cannot fill an unsatisfied required fixed slot. Supply a positional value before the spread, or give the fixed parameter a default.

    Source evidence

    A spread call requires a variadic parameter

    Link
    example.tpzA spread call requires a variadic parameterOpen in Playground
    1. function one(value: int) -> int { value }
    2. one(...[1])
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5004 function-spread-requires-rest at example.tpz:2:1
    Source evidence

    Named call syntax is rejected before argument binding

    Link
    example.tpzNamed call syntax is rejected before argument bindingOpen in Playground
    1. function total(base: int = 10, ...values: int) -> int { base + values.length }
    2. total(base: 1, ...[2])
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-named-call-syntax at example.tpz:2:11
    Source evidence

    Named call syntax is rejected before argument binding

    Link
    example.tpzNamed call syntax is rejected before argument bindingOpen in Playground
    1. function total(base: int = 10, ...values: int) -> int { base + values.length }
    2. total(values: [1])
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-named-call-syntax at example.tpz:2:13
    Source evidence

    A variadic parameter before a fixed parameter

    Link
    example.tpzA variadic parameter before a fixed parameterOpen in Playground
    1. function misplaced(...values: int, last: int) -> int { last }
    target product 5.21.3
    Expected result

    Expected result

    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 --test docs/topaz-reference/templates/functions-generics.test.mjs keeps that nonzero-exit expectation. It is marked TODO for the recorded SELF placement-check limitation; its actual result must be reviewed in CI.

    Source evidence

    Multiple variadic parameters

    Link
    example.tpzMultiple variadic parametersOpen in Playground
    1. function repeated(...first: int, ...second: int) -> () {}
    target product 5.21.3
    Expected result

    Expected result

    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 --test docs/topaz-reference/templates/functions-generics.test.mjs keeps that nonzero-exit expectation. It is marked TODO for the recorded SELF placement-check limitation; its actual result must be reviewed in CI.

    Source evidence

    Distinct parameter names in functions and lambdas

    Link
    example.tpzDistinct parameter names in functions and lambdas
    1. import std.io { writeLine }
    2. function add(left: int, right: int) -> int { left + right }
    3. let addLambda: (int, int) -> int = (left, right) => left + right
    4. writeLine("{add(1, 2)}")
    5. writeLine("{addLambda(3, 4)}")
    Expected outputexit 0
    3
    7
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 3
    2. 7
    Source evidence

    A named function rejects a repeated parameter name

    Link
    example.tpzA named function rejects a repeated parameter nameOpen in Playground
    1. function choose(value: int, value: int) -> int { value }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5008 bindings-local-same-scope-redeclaration at example.tpz:1:29
    Source evidence

    A lambda rejects a repeated parameter name

    Link
    example.tpzA lambda rejects a repeated parameter nameOpen in Playground
    1. let choose: (int, int) -> int = (value, value) => value
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5008 bindings-local-same-scope-redeclaration at example.tpz:1:41
    Source evidence

    Separate parameter lists may reuse a name

    Link
    example.tpzSeparate parameter lists may reuse a name
    1. import std.io { writeLine }
    2. function outer(value: int) -> int {
    3. let next: (int) -> int = (value) => value + 1
    4. next(value)
    5. }
    6. writeLine("{outer(4)}")
    Expected outputexit 0
    5
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 5
    Source evidence

    Empty and populated variadic tails without a default

    Link
    example.tpzEmpty and populated variadic tails without a default
    1. import std.io { writeLine }
    2. function count(...values: int) -> int { values.length }
    3. let empty: Array<int> = []
    4. writeLine("{count()}")
    5. writeLine("{count(1, 2)}")
    6. writeLine("{count(...empty)}")
    Expected outputexit 0
    0
    2
    0
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 0
    2. 2
    3. 0
    Source evidence

    A variadic parameter rejects a default initializer

    Link
    example.tpzA variadic parameter rejects a default initializerOpen in Playground
    1. function count(...values: int = [1]) -> int { values.length }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-variadic-default at example.tpz:1:31
    Source evidence

    A fixed default does not permit a variadic default

    Link
    example.tpzA fixed default does not permit a variadic defaultOpen in Playground
    1. function count(base: int = 10, ...values: int = [1]) -> int { base + values.length }
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 function-variadic-default at example.tpz:1:47
    Source evidence

    A name accepts explicit type arguments

    Link
    example.tpzA name accepts explicit type arguments
    1. import std.io { writeLine }
    2. function identity<T>(value: T) -> T { value }
    3. let value: int = identity<int>(1)
    4. writeLine("{value}")
    Expected outputexit 0
    1
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1
    Source evidence

    A member access accepts explicit type arguments

    Link
    example.tpzA member access accepts explicit type argumentsOpen in Playground
    1. import std.io { writeLine }
    2. import helpers
    3. let value: int = helpers.identity<int>(2)
    4. writeLine("{value}")
    Expected outputexit 0
    2
    
    $ topaz run example.tpz · target product 5.21.3
    helpers.tpzA member access accepts explicit type argumentsOpen in Playground
    1. export function identity<T>(value: T) -> T { value }
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 2
    Source evidence

    A parenthesized callee infers type arguments

    Link
    example.tpzA parenthesized callee infers type arguments
    1. import std.io { writeLine }
    2. function identity<T>(value: T) -> T { value }
    3. let value: int = (identity)(3)
    4. writeLine("{value}")
    Expected outputexit 0
    3
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 3
    Source evidence

    A parenthesized expression does not introduce explicit type arguments

    Link
    example.tpzA parenthesized expression does not introduce explicit type argumentsOpen in Playground
    1. function identity<T>(value: T) -> T { value }
    2. let value: int = (identity)<int>(1)
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5002 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.

    Source evidence

    Parenthesized lambda parameter lists

    Link
    example.tpzParenthesized lambda parameter lists
    1. import std.io { writeLine }
    2. let zero: () -> int = () => 0
    3. let one: (int) -> int = (value) => value + 1
    4. let typed: (int) -> int = (value: int) => value + 1
    5. let pair: (int, int) -> int = (left, right) => left + right
    6. writeLine("{zero()}")
    7. writeLine("{one(1)}")
    8. writeLine("{typed(2)}")
    9. writeLine("{pair(3, 4)}")
    Expected outputexit 0
    0
    2
    3
    7
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 0
    2. 2
    3. 3
    4. 7
    Source evidence

    A bare lambda parameter is rejected

    Link
    example.tpzA bare lambda parameter is rejectedOpen in Playground
    1. let step: (int) -> int = value => value + 1
    Expected outputNonzero exit
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 expected-statement-separator at example.tpz:1:32
    Source evidence

    Record fields preserve settings when reordered

    Link
    example.tpzRecord fields preserve settings when reordered
    1. import std.io { writeLine }
    2. function dimensions(settings: { width: int, height: int }) -> string {
    3. "{settings.width}x{settings.height}"
    4. }
    5. let width = 80
    6. let height = 24
    7. let describe: ({ width: int, height: int }) -> string = dimensions
    8. writeLine(dimensions({ width: width, height: height }))
    9. writeLine(dimensions({ height: height, width: width }))
    10. writeLine(describe({ height: height, width: width }))
    Expected outputexit 0
    80x24
    80x24
    80x24
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 80x24
    2. 80x24
    3. 80x24
    Source evidence

    Related diagnostics

    Link

    TPZ5001

    TPZ5022

    TPZ5523

    TPZ5524

    The catalog owns causes, correction examples, and output details. This page owns the function rules.

    Wrong argument count

    Wrong number of explicit type arguments

    Explicit type arguments are not allowed here

    Unexpected token

    Redeclaration

    Unbound name

    Menu

    Download