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 10 · 38 rules

    Collections and comprehensions

    Choose collection construction forms and check the rules for literals, array spread, and comprehensions.

    Scope and ownership

    Link

    Edition: Topaz 5.21 language mode. Source references identify the SELF implementation behind these rules. Each example records its expected result and verification state.

    This page covers collection construction. See Blocks and control flow for general loops and control transfer, Expressions and operators for indexing, and the Standard library for receiver methods. Records, enums and newtypes covers record updates; Functions and generics covers spread arguments in calls.

    Construction syntax

    Link
    EBNF
    1. ArrayLiteral = "[" (ArrayElement ("," ArrayElement)* ","?)? "]" ;
    2. ArrayElement = Expression | "..." Expression ;
    3. SetLiteral = "set" "{" (Expression ("," Expression)* ","?)? "}" ;
    4. MapLiteral = "map" "{" (MapEntry ("," MapEntry)* ","?)? "}" ;
    5. MapEntry = Expression ":" Expression ;
    6. ArrayComprehension = "[" Clauses "=>" Expression "]" ;
    7. SetComprehension = "set" "{" Clauses "=>" Expression "}" ;
    8. MapComprehension = "map" "{" Clauses "=>" Expression ":" Expression "}" ;
    9. Clauses = ForClause (ForClause | IfClause)* ;
    10. ForClause = "for" Pattern "in" ControlOperand ;
    11. IfClause = "if" ControlOperand ;

    The grammar is transcribed from the linked parser evidence. Expression, Pattern, and ControlOperand are supplied by their respective language definitions.

    Source evidence

    Collection literal entries

    An array literal accepts expressions and ...expression entries. A set literal contains expressions, and a map literal contains key: value entries.

    Why

    Each literal exposes whether it stores a sequence, unique values, or key and value associations. Map entries keep each key beside its value.

    Source evidence

    Comprehension clauses and body

    A comprehension starts with for pattern in (source). Additional clauses use for pattern in (source) or if (condition). The => token introduces the body. A map body has the form key: value.

    Why

    Comprehensions reuse the existing for and if control forms. The final arrow separates selection of bindings from the value produced for them.

    Source evidence

    Literal types and array spread

    Link

    Array literal type

    An array literal forms Array<T> from its element types.

    Why

    A shared element type gives indexing and iteration one type contract. Inferring it from the entries avoids repeating type information for every value.

    Source evidence

    Set literal type

    A set literal forms Set<T> from its element types.

    Why

    A shared element type lets membership and duplicate checks use one value contract. The supplied entries provide the information needed to infer that type.

    Source evidence

    Map literal type

    A map literal forms Map<K, V> from its key and value types.

    Why

    Separate key and value types let lookup check a key without requiring the payload to have the same type. Each side is inferred from its own entries.

    Source evidence

    Context for empty collections

    Why

    Collection syntax does not introduce a separate typing model.

    Source evidence

    Bare empty collections require context

    Why

    The reason a collection needs context is independent of its surface form.

    Source evidence

    Array spread element type

    Spreading a concrete Array<T> contributes elements of type T to the containing array literal.

    Why

    Spread inserts the contents of an array into the surrounding sequence. Its element type must therefore contribute to the result instead of introducing another array layer.

    Source evidence

    Reject a non-array spread operand

    An array spread whose concrete, non-union operand type is not Array<T> produces TPZ5001.

    Why

    Array spread copies stored array elements. Requiring an array avoids adding an implicit conversion from other iterable values during construction.

    Source evidence

    Array construction order

    Array construction appends ordinary values and inserts each spread operand’s elements at the spread position.

    Why

    Arrays preserve positions, so each entry must contribute where it appears. Expanding a spread in place preserves the relative order of its elements.

    Source evidence

    Collection key checks

    Key-capability checking applies to set elements and map keys in literals and comprehensions, independently of map values.

    Why

    Set elements and map keys determine membership and lookup identity. Map values are payloads, so they do not need the key comparison capability.

    Source evidence

    Rejected collection key types

    A function, Map, Set, Range, or ByteBuffer used as a set element or map key produces TPZ5007. A compound key containing one of these types also produces TPZ5007.

    Why

    Keys require a supported equality comparison throughout their structure. Rejecting incompatible components prevents membership and lookup from reaching an unsupported comparison.

    Source evidence

    Admitted keys and stored values

    Map keys and Set elements follow value semantics at insertion. Scalars include integer and floating values, strings, booleans, unit/null, Bytes, Path, URL, Date, BigInt, and Decimal. Option/Result payloads, arrays, records, enum payloads, and newtype contents must recursively be keyable. Map, Set, Range, ByteBuffer, functions, templates, File, JSONValue, Regex, Match, TOMLValue, and RoundingMode are rejected as keys. Imported namespaces and host-provided opaque values are also not keys. Structural guards bound recursive key checks. A generic type parameter passing the static gate is not evidence that every substitution is keyable; the concrete runtime value must still pass this domain check.

    Why

    Stable stored values keep membership and lookup consistent. Insertion follows value semantics, including compound keys.

    Source evidence

    Where collection expectations come from

    Binding annotations, expected call parameters, declared returns, block tails, parentheses, and expected function result types can supply a collection expectation. Empty literals follow empty collection context. A collection expectation does not select one arm from a union. Contextual literal typing does not change collection variance or general assignability.

    Why

    A surrounding type remains useful through grouping and block tails. Sharing that context across bindings, calls, and returns avoids making empty collection typing depend on presentation.

    Source evidence

    Context through collection components

    A matching Array<E>, Set<E>, or Map<K, V> expectation supplies the component types for each emitted element, key, and value. Nonempty literals and comprehension bodies receive those component expectations, including through declared or expected callable results. After successful component checking, a comprehension retains the expected type arguments in its result without further widening. Comprehension iterator sources keep their own inferred types, and filters require bool. A rigid type parameter remains rigid. An incompatible concrete component must still be rejected. Callable result inference retains the actual body constraints for its enclosing comparison. Array spread checks its contributed element type. Collection variance, assignability, and key eligibility are unchanged.

    A matching collection expectation may contain a type parameter fixed by the surrounding generic declaration; that parameter remains a constraint. Fresh call inference still follows the ordinary per-call rules. Context completes missing information and checks concrete expressions using the existing assignability rules. It does not choose a collection arm from a union expectation. An array spread contributes its actual element type, so the spread operand retains its own array type. Set elements and map keys still pass the key-capability checks.

    Why

    A collection expectation already identifies the types of the values being assembled. Passing those component types into every literal and comprehension body gives the same information to nested expressions across collection forms. Comprehension sources can have different element types from their outputs, so their types come from the source expressions. Preserving concrete component constraints keeps contextual inference sound.

    Source evidence

    An empty sibling cannot erase a known type mismatch

    Completing an empty collection from context must preserve the constraints of its concrete siblings. A nested string array cannot satisfy an int-array expectation merely because another map value is empty. SELF currently has a whole-type refinement path that can erase this mismatch; retain the intended rejection while that implementation limitation is reviewed.

    Why

    Filling an unknown element type must not erase a known incompatible value. Otherwise an annotation could admit values that violate the collection type.

    Source evidence

    Comprehension clauses and results

    Link

    Callback methods and comprehensions

    Callback methods such as values.map(f) and values.filter(p) apply existing function values and chain their transformations. A comprehension states source bindings, filters, and emitted values together. It constructs an array, set, or map and can combine several sources.

    Array map and filter evaluate their receiver and callback expression once in ordinary call order. Each method then makes a complete eager pass in element order. It calls its function once per element. A filter retains successful elements in that order. Each method finishes before the next method in a chain begins. Thus values.filter(p).map(f) finishes every call to p before its first call to f.

    A comprehension eagerly builds its result. Its first source evaluates once. Each later source evaluates again for each earlier binding combination that reaches it. Clauses run in written order. Each filter decides whether later clauses and the body run for the current bindings. The body runs before traversal advances to the next reached combination.

    For the same array and fixed pure functions that complete, values.map(f) and [for value in (values) => f(value)] produce the same ordered values. A pure function has the same result for the same arguments and has no observable effects. values.filter(p).map(f) and [for value in (values) if (p(value)) => f(value)] also produce the same ordered values. The second comprehension calls f immediately after a successful p for each element. Effects and failures retain these evaluation boundaries.

    Why

    A callback chain communicates reuse of function values through successive transformations. A comprehension communicates how source bindings and filters construct a new collection. These intentions and their evaluation boundaries differ even when pure functions produce equal values. Both forms preserve that distinction.

    Source evidence

    Nested comprehension clauses

    Each later comprehension clause executes inside the preceding clauses.

    Why

    Later clauses can use earlier bindings because they execute inside those scopes. This gives the clause sequence the same meaning as explicit nested loops.

    Source evidence

    Comprehension filter scope

    A comprehension if filter runs the remaining clauses and body when its condition is true and skips them when it is false.

    Why

    A filter decides whether the remaining work runs for the current bindings. Skipping that work on false avoids computing values that will not enter the result.

    Source evidence

    Accumulate reached body results

    Each successful comprehension body evaluation contributes one element or one map key/value pair.

    Why

    Each reached body supplies one result entry. This keeps the number and order of produced entries tied to successful body evaluations.

    Source evidence

    Comprehension source and pattern types

    For a concrete Array<T>, Set<T>, or Range<T> source, a comprehension checks its pattern against the source element type T.

    Why

    The iteration pattern receives an element, not the collection itself. Using the source element type makes pattern checking agree with each value encountered at runtime.

    Source evidence

    Reject a non-iterable source

    A concrete non-iterable source in a comprehension produces TPZ5001.

    Why

    Iteration requires a defined sequence of elements. Rejecting other values avoids inventing an implicit conversion or a type-dependent notion of iteration.

    Source evidence

    Comprehension filters require bool

    A comprehension if condition must have type bool. A non-boolean condition produces TPZ5001.

    Why

    A filter uses the same boolean condition rule as if. Requiring bool avoids an additional truthiness convention for numbers, strings, or collections.

    Source evidence

    Array comprehension type

    Without a matching array expectation, an array comprehension independently infers and widens its body type T, producing Array<T>. With a matching expectation, component checking and the result type follow collection context propagation.

    Why

    Independent inference supplies a useful collection type without context. A matching expectation supplies component types that remain intact after successful checking.

    Source evidence

    Set comprehension type

    Without a matching set expectation, a set comprehension independently infers and widens its body type T, producing Set<T>. With a matching expectation, component checking and the result type follow collection context propagation.

    Why

    Independent inference supplies a useful collection type without context. A matching expectation supplies component types that remain intact after successful checking.

    Source evidence

    Map comprehension type

    Without a matching map expectation, a map comprehension independently infers and widens its key type K and value type V, producing Map<K, V>. With a matching expectation, component checking and the result type follow collection context propagation.

    Why

    Independent inference supplies a useful collection type without context. A matching expectation supplies component types that remain intact after successful checking.

    Source evidence

    Collection and comprehension evaluation order

    Literal elements and spread sources evaluate in source order. Each map key evaluates before its value. A comprehension reevaluates each later iterator source for every earlier binding combination that reaches it; an if filter controls only the following clauses and body. Map literals and comprehensions evaluate all pairs before the constructor checks for duplicate keys. A duplicate does not erase effects already performed by later pairs.

    Why

    A fixed operand order makes collection effects reproducible. Map construction receives evaluated pairs, so expression evaluation and duplicate validation have separate failure points.

    Source evidence

    Failure while producing a collection

    If an element, iterator source, filter, key, or value faults or propagates an early result, later expressions are not evaluated and no collection result is produced on that path. Effects already performed remain observable. This production failure is distinct from duplicate-map validation, which starts only after all pairs have been accumulated; ordinary faults follow the fault cleanup rule.

    Why

    A failed expression cannot supply a value for construction. Stopping at that point prevents later effects while preserving effects that already happened.

    Source evidence

    Comprehension scopes and arrow boundaries

    Each for source is resolved before that clause introduces its fresh immutable pattern bindings. Later clauses and the body see earlier bindings, and a later for clause may shadow an earlier name. Each source and filter uses the required outer parentheses and ordinary expression grammar inside them. The comprehension body arrow follows the complete parenthesized operand.

    Why

    A source is evaluated before its new pattern binds names, so it cannot accidentally refer to its own new binding. Required operand parentheses separate ordinary lambda syntax from the comprehension body arrow.

    Source evidence

    A refutable pattern does not silently filter

    A comprehension may use a refutable pattern. Each reached element must match. The first mismatch raises runtime TPZ5001 and stops construction. Use an explicit filter or match expression to skip elements.

    Why

    A binding pattern requires an element to have the stated shape. Filtering belongs to if, so a pattern mismatch must not silently discard data.

    Source evidence

    Names inside one pattern must be distinct

    One pattern introduces one scope and must not bind the same name twice. This differs from valid shadowing across separate for clauses. SELF currently misses the same-scope duplicate guard on plain list patterns; the intended TPZ5008 rejection is retained as an implementation limitation.

    Why

    One pattern must give each bound name one value. Repeated names would silently choose between different positions in the same element.

    Source evidence

    Duplicate elements and keys

    Link

    Set order and duplicate elements

    Set literals and comprehensions preserve the order of first occurrence and collapse duplicate elements.

    Reinsertion, removal, traversal, and display follow Map and Set insertion order.

    Why

    Set membership ignores repeated equal elements. Preserving first encounter order also keeps iteration reproducible without rearranging the surviving values.

    Source evidence

    Map and Set insertion order

    Map keys, values, and entries are observed in insertion order. Traversing those views with for preserves that order. Map display uses the same order. Inserting a new key appends it. Inserting an existing key replaces its value without moving the key. Removing a key preserves the relative order of surviving entries.

    Set traversal and display follow insertion order. Adding an existing element keeps its position. Removing an element preserves the relative order of surviving elements. Set construction follows first occurrence order. Map and Set equality remains independent of this observation order.

    Insertion and transfer follow collection value semantics. Collection equality is independent of insertion order.

    Why

    Map and Set use the same order rule. Preserving insertion order makes traversal and display reproducible. Replacing a value does not rearrange unrelated entries.

    Source evidence

    Repeated map literal keys

    Repeating a string or integer literal key in a map literal produces TPZ5602.

    Why

    Two entries for the same key cannot both survive as separate associations. Rejecting an evident collision before execution catches accidental overwrites early.

    Source evidence

    Computed map key collisions

    When computed keys collide during map literal or comprehension construction, execution fails with TPZ4601 without replacing the earlier value.

    Why

    Computed keys can collide after evaluation. Rejecting the collision prevents source order from silently choosing which value survives.

    Source evidence

    Computed map collision location

    A computed duplicate key faults at the span of the complete map literal, whose start is the map keyword. The fault location is not the second key expression. The source-backed expectation for this fixture is example.tpz:2:14; the public CLI emission is tracked as an implementation limitation.

    Why

    A duplicate key is a conflict within the constructed map. Pointing to that construction identifies the operation that could not produce a value.

    Source evidence
    • parseMap at 151141d7bb44 · 547-575
    • emitMap at 151141d7bb44 · 570-587
    • builtin_map_of at 151141d7bb44 · 693-713
    Ruletopaz.rule.structures.source.key-equality

    Canonical key equality

    Key insertion follows value semantics. Canonical key equality compares the stored value family and then its contents recursively. Arrays compare elementwise; records compare field names and values; nominal records, enums, and newtypes retain declaration identity. Floating signed zeros compare equal, while NaN does not equal any key, including itself. Integer and floating keys have distinct tags. Equivalent constant spellings do not define different language values merely because static duplicate detection recognizes only some forms.

    Why

    Key comparison uses stored value contents while preserving scalar tags and nominal identity. A nominal Eq method does not replace that key identity. Different constant spellings must not create a separate key identity.

    Source evidence

    Duplicate constant boolean keys

    A repeated constant boolean key is a duplicate just as a repeated constant string or integer key is. SELF currently parses booleans as expression/boolean but its constant-key checker tests expression/bool. The intended TPZ5602 rejection is retained as a product test, and the mismatched syntax kind is an implementation limitation.

    Why

    A boolean key has the same identity whether it is written directly or computed. Detecting a known collision early preserves the runtime duplicate-key rule.

    Source evidence

    Examples and expected results

    Link

    Array, set, and map literals

    Link
    example.tpzArray, set, and map literals
    1. let values: Array<int> = [1, 2, 3]
    2. let names: Set<string> = set { "Ada", "Lin" }
    3. let counts: Map<string, int> = map { "Ada": 1, "Lin": 2 }
    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.

    Expected stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    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
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Give empty collections a contextual type

    Link
    example.tpzGive empty collections a contextual type
    1. let values: Array<int> = []
    2. let names: Set<string> = set {}
    3. let counts: Map<string, int> = map {}
    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.

    Expected stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    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
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Append an array at the spread position

    Link
    example.tpzAppend an array at the spread position
    1. import std.io { writeLine }
    2. let values = [0, ...[1, 2], 3]
    3. for value in (values) {
    4. writeLine("{value}")
    5. }
    Recorded outputexit 0
    0
    1
    2
    3
    
    $ topaz run example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 0
    2. 1
    3. 2
    4. 3
    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. 0
    2. 1
    3. 2
    4. 3

    No stderr.

    • Passed · expected 0; observed 0
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Nest clauses and filter the remaining body

    Link
    example.tpzNest clauses and filter the remaining body
    1. import std.io { writeLine }
    2. let values = [for x in ([1, 2]) for y in ([10, 20]) if (x == 2) => x + y]
    3. for value in (values) {
    4. writeLine("{value}")
    5. }
    Recorded outputexit 0
    12
    22
    
    $ topaz run example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 12
    2. 22
    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. 12
    2. 22

    No stderr.

    • Passed · expected 0; observed 0
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Construct a set from repeated body values

    Link
    example.tpzConstruct a set from repeated body values
    1. import std.io { writeLine }
    2. let values = set { for n in ([1, 2, 3, 4]) => n % 2 }
    3. for value in (values) {
    4. writeLine("{value}")
    5. }
    Recorded outputexit 0
    1
    0
    
    $ topaz run example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1
    2. 0
    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. 1
    2. 0

    No stderr.

    • Passed · expected 0; observed 0
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Produce key/value pairs in a map comprehension

    Link
    example.tpzProduce key/value pairs in a map comprehension
    1. let squares: Map<int, int> = map { for n in ([1, 2, 3]) if (n > 1) => n: n * n }
    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.

    Expected stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    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
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Reject a bare empty array without context

    Link
    example.tpzReject a bare empty array without contextOpen in Playground
    1. let values = []
    Recorded outputexit 1
    No stdout.
    error[TPZ5020]: `[]` needs a contextual type (§22.1): annotate the binding or the expected element type
     --> example.tpz:1:14
      |
    1 | let values = []
      |              ^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5020 bare-empty-array-without-context at example.tpz:1:14
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ5020]: `[]` needs a contextual type (§22.1): annotate the binding or the expected element type
    2. --> example.tpz:1:14
    3. |
    4. 1 | let values = []
    5. | ^^
    6. example.tpz: 1 type diagnostic
    • Passed · expected nonzero; observed 1
    • Passed · stdout matches the authored expectation
    • Passed · checking TPZ5020; cause bare-empty-array-without-context; primary location asserted; additional diagnostics allow
    Source evidence

    Reject a concrete non-array spread operand

    Link
    example.tpzReject a concrete non-array spread operandOpen in Playground
    1. let values = [...1]
    Recorded outputexit 1
    No stdout.
    error[TPZ5001]: array spread needs an `Array`, found `1`
     --> example.tpz:1:18
      |
    1 | let values = [...1]
      |                  ^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 concrete-non-array-spread at example.tpz:1:18
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ5001]: array spread needs an `Array`, found `1`
    2. --> example.tpz:1:18
    3. |
    4. 1 | let values = [...1]
    5. | ^
    6. example.tpz: 1 type diagnostic
    • Passed · expected nonzero; observed 1
    • Passed · stdout matches the authored expectation
    • Passed · checking TPZ5001; cause concrete-non-array-spread; primary location asserted; additional diagnostics allow
    Source evidence

    Reject an integer comprehension filter

    Link
    example.tpzReject an integer comprehension filterOpen in Playground
    1. let values = [for n in ([1, 2]) if (1) => n]
    Recorded outputexit 1
    No stdout.
    error[TPZ5001]: expected `bool`, found `int`
     --> example.tpz:1:34
      |
    1 | let values = [for n in [1, 2] if 1 => n]
      |                                  ^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 non-boolean-comprehension-filter at example.tpz:1:37
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ5001]: expected `bool`, found `int`
    2. --> example.tpz:1:34
    3. |
    4. 1 | let values = [for n in [1, 2] if 1 => n]
    5. | ^
    6. example.tpz: 1 type diagnostic
    • Passed · expected nonzero; observed 1
    • Passed · stdout matches the authored expectation
    • Passed · checking TPZ5001; cause non-boolean-comprehension-filter; primary location asserted; additional diagnostics allow
    Source evidence

    Reject a repeated identical string key

    Link
    example.tpzReject a repeated identical string keyOpen in Playground
    1. let values = map { "same": 1, "same": 2 }
    Recorded outputexit 1
    No stdout.
    error[TPZ5602]: duplicate key in `map { … }` literal
     --> example.tpz:1:31
      |
    1 | let values = map { "same": 1, "same": 2 }
      |                               ^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5602 repeated-identical-string-key-in-map-literal at example.tpz:1:31
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ5602]: duplicate key in `map { … }` literal
    2. --> example.tpz:1:31
    3. |
    4. 1 | let values = map { "same": 1, "same": 2 }
    5. | ^^^^^^
    6. example.tpz: 1 type diagnostic
    • Passed · expected nonzero; observed 1
    • Passed · stdout matches the authored expectation
    • Passed · checking TPZ5602; cause repeated-identical-string-key-in-map-literal; primary location asserted; additional diagnostics allow
    Source evidence

    Reject colliding computed map keys at runtime

    Link
    example.tpzReject colliding computed map keys at runtime
    1. function key(value: int) -> int { value % 2 }
    2. let values = map { key(1): 10, key(3): 30 }
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    The required primary-location contract is Pending.

    Source evidence

    Repair the computed-key collision

    Link
    example.tpzRepair the computed-key collision
    1. function key(value: int) -> int { value % 2 }
    2. let values: Map<int, int> = map { key(1): 10, key(2): 20 }
    Recorded outputexit 0
    No stdout.
    $ topaz run example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    No stdout.

    No stderr.

    • Passed · expected 0; observed 0
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Reject a computed collision at the map literal start

    Link
    example.tpzReject a computed collision at the map literal start
    1. function key(value: int) -> int { value % 2 }
    2. let values = map { key(1): 10, key(3): 30 }
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ4601 computed-map-key-collision at example.tpz:2:14
    Source evidence
    • parseMap at 151141d7bb44 · 547-575
    • emitMap at 151141d7bb44 · 570-587
    • builtin_map_of at 151141d7bb44 · 693-713

    Run the corresponding map with distinct computed keys

    Link
    example.tpzRun the corresponding map with distinct computed keys
    1. function key(value: int) -> int { value % 2 }
    2. let values = map { key(1): 10, key(2): 30 }
    Expected outputexit 0
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Source evidence
    • emitMap at 151141d7bb44 · 570-587
    • builtin_map_of at 151141d7bb44 · 693-713

    Store and deduplicate array key values before later mutation

    Link
    example.tpzStore and deduplicate array key values before later mutation
    1. import std.io
    2. let mut source = [1]
    3. let keys = set { source, [1], [2] }
    4. source.push(9)
    5. for key in (keys) {
    6. io.writeLine("{key.length}")
    7. }
    Expected outputexit 0
    1
    1
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1
    2. 1

    Set elements follow value semantics. Changing source leaves the stored array values and their membership unchanged.

    Source evidence

    Reject a Map used as a Set element

    Link
    example.tpzReject a Map used as a Set elementOpen in Playground
    1. let keys = set { map { "a": 1 } }
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5007 structures-map-is-not-keyable at example.tpz:1:12
    Source evidence

    Use recursively keyable arrays as Set elements

    Link
    example.tpzUse recursively keyable arrays as Set elements
    1. let keys = set { [1], [2] }
    Expected outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Expected stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    Source evidence

    Keep numeric key families distinct and collapse signed floating zero

    Link
    example.tpzKeep numeric key families distinct and collapse signed floating zero
    1. import std.io
    2. let zeros = set { 0.0, -0.0 }
    3. let tagged = set { 1, 1.0 }
    4. let mut zeroCount = 0
    5. for value in (zeros) { zeroCount += 1 }
    6. let mut taggedCount = 0
    7. for value in (tagged) { taggedCount += 1 }
    8. io.writeLine("{zeroCount}:{taggedCount}")
    Expected outputexit 0
    1:2
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1:2
    Source evidence

    Reject repeated true keys in a map literal

    Link
    example.tpzReject repeated true keys in a map literalOpen in Playground
    1. let values = map { true: 1, true: 2 }
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5602 structures-duplicate-boolean-map-key at example.tpz:1:29
    Source evidence

    Check distinct true and false keys

    Link
    example.tpzCheck distinct true and false keys
    1. let values = map { true: 1, false: 2 }
    Expected outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Expected stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    Source evidence

    Observe literal and nested comprehension evaluation order

    Link
    example.tpzObserve literal and nested comprehension evaluation order
    1. import std.io
    2. function mark(label: string, value: int) -> int {
    3. io.writeLine(label)
    4. value
    5. }
    6. function source(n: int) -> Array<int> {
    7. io.writeLine("source:{n}")
    8. [n, n + 10]
    9. }
    10. function outerAllowed(n: int) -> bool {
    11. io.writeLine("outer:{n}")
    12. n > 0
    13. }
    14. function keep(n: int) -> bool {
    15. io.writeLine("filter:{n}")
    16. n < 10
    17. }
    18. let values = [mark("array1", 1), ...[mark("spread", 2)], mark("array3", 3)]
    19. let pairs = map { mark("key1", 1): mark("value1", 10), mark("key2", 2): mark("value2", 20) }
    20. let nested = [for outer in ([0, 1, 2]) if (outerAllowed(outer)) for inner in (source(outer)) if (keep(inner)) => mark("body:{inner}", inner)]
    21. io.writeLine("done")
    Expected outputexit 0
    array1
    spread
    array3
    key1
    value1
    key2
    value2
    outer:0
    outer:1
    source:1
    filter:1
    body:1
    filter:11
    outer:2
    source:2
    filter:2
    body:2
    filter:12
    done
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. array1
    2. spread
    3. array3
    4. key1
    5. value1
    6. key2
    7. value2
    8. outer:0
    9. outer:1
    10. source:1
    11. filter:1
    12. body:1
    13. filter:11
    14. outer:2
    15. source:2
    16. filter:2
    17. body:2
    18. filter:12
    19. done
    Source evidence

    Stop producing elements after Result propagation

    Link
    example.tpzStop producing elements after Result propagation
    1. import std.io
    2. function item(label: string, fail: bool) -> Result<int, string> {
    3. io.writeLine(label)
    4. if (fail) { Err("stop") } else { Ok(1) }
    5. }
    6. function build() -> Result<Array<int>, string> {
    7. let values = [item("first", false)?, item("second", true)?, item("third", false)?]
    8. Ok(values)
    9. }
    10. let outcome = build()
    11. match (outcome) {
    12. case Err(message) => io.writeLine(message)
    13. case Ok(_) => io.writeLine("unexpected success")
    14. }
    Expected outputexit 0
    first
    second
    stop
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. first
    2. second
    3. stop
    Source evidence
    • emitArray at 151141d7bb44 · 539-567
    • emitQuestion at 151141d7bb44 · 1927-1934

    Reject a duplicate after evaluating all map pairs

    Link
    example.tpzReject a duplicate after evaluating all map pairs
    1. import std.io
    2. function mark(label: string, value: int) -> int {
    3. io.writeLine(label)
    4. value
    5. }
    6. let values = map { mark("key1", 1): mark("value1", 10), mark("key2", 1): mark("value2", 20), mark("key3", 3): mark("value3", 30) }
    7. io.writeLine("after")
    Expected outputNonzero exit
    key1
    value1
    key2
    value2
    key3
    value3
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ4601 computed-map-key-collision at example.tpz:6:14
    Expected stdout
    1. key1
    2. value1
    3. key2
    4. value2
    5. key3
    6. value3
    Source evidence
    • emitMap at 151141d7bb44 · 570-587
    • builtin_map_of at 151141d7bb44 · 698-713

    Check annotations, calls, returns, callbacks, and nested empties

    Link
    example.tpzCheck annotations, calls, returns, callbacks, and nested emptiesOpen in Playground
    1. function empty<T>() -> Array<T> { [] }
    2. function count(values: Array<int>) -> int { values.length }
    3. function invoke(callback: () -> Array<int>) -> Array<int> { callback() }
    4. let nested: Array<Array<int>> = [[], [1]]
    5. let items: Array<int | string> = [1, "text"]
    6. let n = count([])
    7. let callback: () -> Array<int> = () => []
    8. let result = invoke(() => [])
    9. let parenthesized: Array<int> = ([])
    10. let block: Array<int> = { [] }
    11. let keys: Set<int> = set {}
    12. let table: Map<string, int> = map {}
    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 bare empty Set without context

    Link
    example.tpzReject a bare empty Set without contextOpen in Playground
    1. let missing = set {}
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5020 structures-empty-collection-context at example.tpz:1:15
    Source evidence

    Give the empty Set an element type

    Link
    example.tpzGive the empty Set an element typeOpen in Playground
    1. let present: Set<int> = set {}
    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 concrete mismatch in a nested array

    Link
    example.tpzReject a concrete mismatch in a nested arrayOpen in Playground
    1. let nested: Array<Array<int>> = [["text"]]
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 structures-nested-array-element-type at example.tpz:1:35
    Source evidence

    Match the nested array element expectation

    Link
    example.tpzMatch the nested array element expectationOpen in Playground
    1. let nested: Array<Array<int>> = [[1]]
    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

    Preserve a known mismatch beside a nested empty value

    Link
    example.tpzPreserve a known mismatch beside a nested empty valueOpen in Playground
    1. let values: Array<Map<string, Array<int>>> = [
    2. map { "bad": ["text"], "empty": [] }
    3. ]
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 structures-nested-array-element-type at example.tpz:2:17
    Source evidence

    Complete the empty value without a conflicting sibling

    Link
    example.tpzComplete the empty value without a conflicting siblingOpen in Playground
    1. let values: Array<Map<string, Array<int>>> = [
    2. map { "bad": [1], "empty": [] }
    3. ]
    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

    Shadow across clauses and delimit source or filter lambdas

    Link
    example.tpzShadow across clauses and delimit source or filter lambdas
    1. import std.io
    2. let values = [for x in ([1, 2]) for x in ([x, x + 10]) => x]
    3. for value in (values) { io.writeLine("{value}") }
    4. let selected = [for x in ((() => [1, 2])()) if (((n: int) => n > 1)(x)) => x]
    5. for value in (selected) { io.writeLine("selected:{value}") }
    Expected outputexit 0
    1
    11
    2
    12
    selected:2
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1
    2. 11
    3. 2
    4. 12
    5. selected:2
    Source evidence

    Collect when every element matches the refutable pattern

    Link
    example.tpzCollect when every element matches the refutable pattern
    1. import std.io
    2. let values = [for Some(x) in ([Some(1), Some(2)]) => x]
    3. for value in (values) { io.writeLine("{value}") }
    Expected outputexit 0
    1
    2
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1
    2. 2
    Source evidence

    Reject a repeated name within one list pattern

    Link
    example.tpzReject a repeated name within one list patternOpen in Playground
    1. let values = [for [x, x] in ([[1, 2]]) => x]
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5008 structures-duplicate-pattern-binding at example.tpz:1:23
    Source evidence

    Use distinct names within the list pattern

    Link
    example.tpzUse distinct names within the list pattern
    1. let values = [for [x, y] in ([[1, 2]]) => x + y]
    Expected outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Expected stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)
    Source evidence

    Stop at a nonmatching element

    Link
    example.tpzStop at a nonmatching element
    1. import std.io
    2. let values = [for Some(x) in ([Some(1), None(), Some(3)]) => x]
    3. io.writeLine("after")
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ5001 structures-for-pattern-nonmatch at example.tpz:2:14
    Source evidence

    Check every literal component from its collection context

    Link
    example.tpzCheck every literal component from its collection contextOpen in Playground
    1. newtype Wrapped<T> = T
    2. let array: Array<Wrapped<int>> = [Wrapped(1)]
    3. let keys: Set<Wrapped<int>> = set { Wrapped(2) }
    4. let table: Map<Wrapped<int>, Wrapped<string>> = map { Wrapped(3): Wrapped("three") }
    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

    Check emitted comprehension components from their result context

    Link
    example.tpzCheck emitted comprehension components from their result contextOpen in Playground
    1. newtype Wrapped<T> = T
    2. let array: Array<Wrapped<int>> = [for item in ([1, 2]) => Wrapped(item)]
    3. let keys: Set<Wrapped<int>> = set { for item in ([1, 2]) => Wrapped(item) }
    4. let table: Map<Wrapped<int>, Wrapped<string>> = map { for item in ([1, 2]) => Wrapped(item): Wrapped("{item}") }
    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

    Carry collection context through declared and expected callable results

    Link
    example.tpzCarry collection context through declared and expected callable resultsOpen in Playground
    1. newtype Wrapped<T> = T
    2. function wrap<T>(value: T) -> Array<Wrapped<T>> { [Wrapped(value)] }
    3. let callback: () -> Set<Wrapped<int>> = () => set { Wrapped(1) }
    4. let result: Array<Wrapped<int>> = wrap(2)
    5. let keys = callback()
    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 concrete mismatch inside a contextual set

    Link
    example.tpzReject a concrete mismatch inside a contextual setOpen in Playground
    1. let values: Set<Array<int>> = set { ["text"] }
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 structures-nested-array-element-type at example.tpz:1:38
    Source evidence

    Supply a compatible element in the same contextual set

    Link
    example.tpzSupply a compatible element in the same contextual setOpen in Playground
    1. let values: Set<Array<int>> = set { [1] }
    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

    Keep map values outside the set key domain under an annotation

    Link
    example.tpzKeep map values outside the set key domain under an annotationOpen in Playground
    1. let keys: Set<Map<string, int>> = set { map { "a": 1 } }
    Expected outputNonzero exit
    No stdout.
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5007 structures-map-is-not-keyable at example.tpz:1:11
    Source evidence

    Use a keyable collection element under an annotation

    Link
    example.tpzUse a keyable collection element under an annotationOpen in Playground
    1. let keys: Set<Array<int>> = set { [1] }
    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

    Inferred comprehension types

    Link
    example.tpzInferred comprehension typesOpen in Playground
    1. let inferredArray = [for item in ([0]) => 1]
    2. let array: Array<int> = inferredArray
    3. let inferredSet = set { for item in ([0]) => 1 }
    4. let keys: Set<int> = inferredSet
    5. let inferredMap = map { for item in ([0]) => 1: "one" }
    6. let table: Map<int, string> = inferredMap
    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

    Array comprehension with an expected literal type

    Link
    example.tpzArray comprehension with an expected literal typeOpen in Playground
    1. let array: Array<1> = [for item in ([0]) => 1]
    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

    Set comprehension with an expected literal type

    Link
    example.tpzSet comprehension with an expected literal typeOpen in Playground
    1. let keys: Set<1> = set { for item in ([0]) => 1 }
    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

    Map comprehension with an expected literal type

    Link
    example.tpzMap comprehension with an expected literal typeOpen in Playground
    1. let table: Map<1, "one"> = map { for item in ([0]) => 1: "one" }
    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

    Reuse functions through callback methods

    Link
    example.tpzReuse functions through callback methods
    1. import std.io
    2. function addPadding(width: int) -> int { width + 2 }
    3. function double(width: int) -> int { width * 2 }
    4. let widths = [10, 20]
    5. let chained = widths.map(addPadding).map(double)
    6. let constructed = [for width in (widths) => double(addPadding(width))]
    7. for width in (chained) {
    8. io.writeLine("callback {width}")
    9. }
    10. for width in (constructed) {
    11. io.writeLine("comprehension {width}")
    12. }
    Expected outputexit 0
    callback 24
    callback 44
    comprehension 24
    comprehension 44
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. callback 24
    2. callback 44
    3. comprehension 24
    4. comprehension 44
    Source evidence

    Construct a collection from filtered sources

    Link
    example.tpzConstruct a collection from filtered sources
    1. import std.io
    2. let widths = [10, 20]
    3. let paddings = [1, 2]
    4. let outerWidths = [for width in (widths) if (width > 10) for padding in (paddings) => width + padding * 2]
    5. for width in (outerWidths) {
    6. io.writeLine("{width}")
    7. }
    Expected outputexit 0
    22
    24
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 22
    2. 24
    Source evidence

    Observe complete callback passes and per-element comprehension work

    Link
    example.tpzObserve complete callback passes and per-element comprehension work
    1. import std.io
    2. function source() -> Array<int> {
    3. io.writeLine("source")
    4. [1, 2, 3]
    5. }
    6. function selected(value: int) -> bool {
    7. io.writeLine("select {value}")
    8. value > 1
    9. }
    10. function convert(value: int) -> int {
    11. io.writeLine("convert {value}")
    12. value * 10
    13. }
    14. function predicate() -> (int) -> bool {
    15. io.writeLine("predicate")
    16. selected
    17. }
    18. function transformation() -> (int) -> int {
    19. io.writeLine("transformation")
    20. convert
    21. }
    22. io.writeLine("callback chain")
    23. let chained = source().filter(predicate()).map(transformation())
    24. io.writeLine("comprehension")
    25. let constructed = [for value in (source()) if (selected(value)) => convert(value)]
    26. io.writeLine("results")
    27. for value in (chained) {
    28. io.writeLine("callback {value}")
    29. }
    30. for value in (constructed) {
    31. io.writeLine("comprehension {value}")
    32. }
    Expected outputexit 0
    callback chain
    source
    predicate
    select 1
    select 2
    select 3
    transformation
    convert 2
    convert 3
    comprehension
    source
    select 1
    select 2
    convert 2
    select 3
    convert 3
    results
    callback 20
    callback 30
    comprehension 20
    comprehension 30
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. callback chain
    2. source
    3. predicate
    4. select 1
    5. select 2
    6. select 3
    7. transformation
    8. convert 2
    9. convert 3
    10. comprehension
    11. source
    12. select 1
    13. select 2
    14. convert 2
    15. select 3
    16. convert 3
    17. results
    18. callback 20
    19. callback 30
    20. comprehension 20
    21. comprehension 30
    Source evidence

    Keep a Map key in place when replacing its value

    Link
    example.tpzKeep a Map key in place when replacing its value
    1. import std.io { writeLine }
    2. let mut values = map { "first": 1, "middle": 2, "last": 3 }
    3. values.insert("middle", 20)
    4. for key in (values.keys) { writeLine(key) }
    5. for value in (values.values) { writeLine("{value}") }
    6. for entry in (values.entries) { writeLine("{entry.key}={entry.value}") }
    7. writeLine("{values}")
    Expected outputexit 0
    first
    middle
    last
    1
    20
    3
    first=1
    middle=20
    last=3
    Map{first: 1, middle: 20, last: 3}
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. first
    2. middle
    3. last
    4. 1
    5. 20
    6. 3
    7. first=1
    8. middle=20
    9. last=3
    10. Map{first: 1, middle: 20, last: 3}
    Source evidence

    Keep surviving Map entries in order after removal

    Link
    example.tpzKeep surviving Map entries in order after removal
    1. import std.io { writeLine }
    2. let mut values = map { "first": 1, "removed": 2, "third": 3, "last": 4 }
    3. values.remove("removed")
    4. for entry in (values.entries) { writeLine("{entry.key}={entry.value}") }
    5. writeLine("{values}")
    Expected outputexit 0
    first=1
    third=3
    last=4
    Map{first: 1, third: 3, last: 4}
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. first=1
    2. third=3
    3. last=4
    4. Map{first: 1, third: 3, last: 4}
    Source evidence

    Keep surviving Set elements in order after removal

    Link
    example.tpzKeep surviving Set elements in order after removal
    1. import std.io { writeLine }
    2. let mut values = set { 3, 1, 4, 2 }
    3. values.add(1)
    4. values.remove(1)
    5. for value in (values) { writeLine("{value}") }
    6. writeLine("{values}")
    Expected outputexit 0
    3
    4
    2
    Set{3, 4, 2}
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 3
    2. 4
    3. 2
    4. Set{3, 4, 2}
    Source evidence

    Pending contracts

    Link

    Related diagnostics and references

    Link

    Type could not be inferred

    Value is not comparable or keyable

    Duplicate key in map literal

    Duplicate runtime map key

    TPZ5001

    Functions and generics

    Records, enums and newtypes

    Redeclaration

    Runtime value guard

    Menu

    Download