Scope and ownership
СсылкаThis page covers source modules, dotted module paths, import bindings, exports, and visibility. Function declarations and bounds belong to Functions and generics. The check command owns entry-file and source-root selection. Dependency acquisition, locks, targets, and individual standard-library APIs have separate owners.
Import and export syntax
СсылкаModulePath = Identifier ("." Identifier)* ;ImportItem = NamespaceImport | SelectedImport ;NamespaceImport = "import" ModulePath ("as" Identifier)? ;SelectedImport ="import" ModulePath "{" ImportSpec ("," ImportSpec)* ","? "}" ;ImportSpec = Identifier ("as" Identifier)? ;ExportShape = "export" ExportableDeclaration ;
This source-syntax excerpt is transcribed from the parser. Identifier spelling, statement separators, declaration bodies, and binding patterns use their own productions.
The complete grammar applies identifier-equality guards to aliases: a namespace alias differs from the final module-path segment, and a selected alias differs from the selected source name. This excerpt shows the production shape; the alias rule specifies that additional constraint.
Files and the source program
СсылкаThe uniform initialization rules are the recommendation recorded in PR #41 for the remaining 6.0 design work. Current SELF differences are listed as limitations with unchanged expected assertions. The example scope remains Topaz 5.21 / public product 5.21.3 until the separate documentation version split.
Source paths and module identity
An ordinary source module uses a dotted identifier path. Under the selected source root, each dot becomes a path separator and the file name ends in .. For example, geometry. selects geometry/. Its logical identity is the dotted relative path without the extension.
Причина
A dotted name gives each source module one logical identity independent of the host path separator. The same name determines the source file.
The source program
The entry file and the source files reached transitively through its imports form the source program.
Причина
Following imports includes the files needed by the entry program without making unrelated neighboring files part of it.
Import placement
Imports must precede every other top-level item in a file. A later import is rejected with TPZ2010.
Причина
A single prologue makes dependencies visible before executable items. Import placement then does not suggest an order among those items.
The same statements in every source file
Entry files and imported files use the same top-level statement grammar. Both admit declarations, free expressions, assignments, and loops. Binding initializers and free expressions use the ordinary effect rules. Import placement, visibility, mutability, control-flow targets, and all other context checks apply equally to both file roles. Importing a file does not add a statement-form restriction.
Причина
The meaning of a source file should not depend on whether it is selected as the entry or reached through an import. Effectful binding initializers already run during module initialization; deterministic ordering and readiness rules address those effects directly. Uniform statement forms let ordinary general-purpose code move between files without a wrapper function or dummy binding.
Dependency order and one initialization
Resolve the complete source program before initialization. Initialize source modules serially, completing every dependency before its importer. At each step, choose the lexicographically smallest canonical logical module identity among modules whose dependencies have completed; compare identities by Unicode scalar value. Import spelling order and local aliases do not affect this order. After constant processing, execute ordinary top-level items in source order. Every module initializes exactly once per program invocation, including when multiple import paths reach it in a diamond. All importers share the same completed module state. A new program invocation, including a new host invocation of an exported function, creates fresh module state and repeats initialization.
Причина
A file has one logical identity and one initialized state within an invocation. A dependency must finish before its importer can use it. Choosing the smallest ready identity makes the result stable when import lines or local aliases change, and sharing diamond dependencies prevents duplicate initialization effects.
Reject cycles before initialization
A source import cycle, including a module importing itself, is rejected with TPZ3006 during resolution. The diagnostic identifies an import edge in the cycle. No module initialization or entry execution begins for a rejected graph. Break the cycle by moving shared declarations into a dependency or removing the back edge.
Причина
A cycle has no dependency-first initialization order. Rejecting it before effects begin keeps every import bound to a fully initialized module and avoids a second set of rules for partially initialized exports.
Read a binding after initialization
Причина
A file's role does not change the meaning of its bindings.
An initialization fault stops the invocation
If module initialization faults, abort the program invocation immediately. Do not execute remaining items in that module, initialize later modules, or start a waiting importer. Already completed effects remain visible; initialization provides no rollback. Report the original fault code and primary source location. An added initialization-context message does not change that diagnostic identity.
Причина
Initialization uses ordinary execution and effects. Stopping at the first fault preserves the dependency guarantee, while retaining the original diagnostic locates the failing operation. General host effects cannot be promised transactional rollback.
Namespace and selected imports
СсылкаNamespace import bindings
A namespace import binds the final path segment as its local namespace name. An explicit as alias supplies that name instead. Select a declaration with namespace..
Причина
A namespace groups a module's exported names under one local binding. An alias resolves collisions between modules with the same final path segment.
Selected import bindings
A selected import binds each chosen export directly under its source name or its selection alias. Renaming the local binding preserves which source declaration it denotes. A selection list creates no namespace binding.
Причина
Selecting exports makes each imported dependency explicit in the local scope. An alias can resolve a local name collision while retaining the source declaration.
An alias changes the local name
Omit as when an import keeps its default binding name. A namespace alias must differ from the final module-path segment; a selected alias must differ from that selected source name. An explicit alias repeating the default identifier is rejected with TPZ2009 during parsing, at the alias identifier. An alias that changes the local name remains permitted under the ordinary import visibility and collision rules.
The intended new diagnostic message is “redundant import alias {name}; omit as {name}”. Here {name} is the alias identifier. This is the proposed contract, not an observed current SELF message. Current SELF accepts the redundant form, as recorded in the limitation. TPZ2009 already canonically identifies unsupported module export/import composition; this rule adds a distinct cause within that identity.
Причина
The default namespace or selected source name already defines the local binding. Repeating that name after as creates a second spelling for exactly the same import without adding information. Omitting a redundant alias keeps one spelling for the default binding, while an actual rename remains available to choose a different local name.
Selection-list requirements
A selection list must contain at least one name. Selected source names and resulting local names must each be unique. Violating these requirements is rejected with TPZ2011.
Причина
An empty selection introduces no names. Repeated source or local names would duplicate an import or leave a local binding ambiguous.
Choose a namespace or selection
A namespace alias and a selection list cannot appear in the same import item. Their combination is rejected with TPZ2009.
Причина
A namespace binding and a selection introduce different local names. Separating them keeps one import item from creating both sets implicitly.
One import item per module
A logical module may appear in at most one import item in an importing file. Repeating it is rejected with TPZ3017.
Причина
One import item keeps a module's dependency and local naming choices together. Repeated items would split the same dependency across declarations.
Exports and read-only import bindings
СсылкаPublic and private declarations
Prefix an otherwise valid function, let, const, type alias, enum, record, newtype, or protocol declaration with export to publish its binding. Without that prefix, the declaration remains module-private.
Причина
Private declarations can change without changing a module's public names. Placing export on the declaration gives each published binding one visible definition.
The shape of an exported binding
An exported immutable let uses an ordinary let pattern and optional type annotation. The pattern must bind at least one name; otherwise TPZ2007 rejects it during parsing. Every bound name becomes an immutable export with its module-and-name identity. Evaluate the initializer once, match the complete pattern, then install all bindings. Ordinary pattern typing, duplicate-name, and refutability checks still apply. If evaluation or matching faults, install no binding from that pattern and stop module initialization; earlier external effects remain. Check every resolved bound type for private nominal exposure. Public types are the extracted binding types, not the temporary initializer container. Module exports are published after successful initialization.
Причина
Export changes visibility, so an immutable binding uses the same pattern and type rules in a private or public declaration. Requiring temporary private bindings would repeat the same decomposition. Each bound name is a public module binding; a pattern without a name publishes nothing and uses plain let. The initializer and pattern match therefore stay one operation, independent of how many names become public.
Exported bindings are immutable
An exported let binding must be immutable. The form export let mut is rejected with TPZ3011 during resolution.
Причина
An immutable exported binding prevents another module from depending on reassignment of shared module state. Updates can pass through an exported function with an explicit interface.
Namespace imports and selected exports
A namespace import may target a module with an empty export table. That module initializes normally and the bound namespace has no public members. Selecting a private or absent name is rejected with TPZ3009 during resolution, including when the target exports no names. Initialization does not require a dummy export or a separate import form.
Причина
Imports expose only public declarations, so selecting a name must consult the export table. Initialization is independent of that table: a module used for its effects needs the same namespace import as any other module, without a dummy export or a separate side-effect import syntax.
Visibility through a namespace
A value or type selected through a namespace must name an exported declaration. The requirement applies in every context, including record field defaults. A private or absent member is rejected with TPZ3009 during resolution.
Причина
Namespace access must respect the same public names as selected imports. Qualification must not grant access to private module declarations.
Rebinding imported declarations
Direct replacement of a selected imported binding, including an alias, or an imported namespace member is rejected during resolution with TPZ3015. This rejection precedes the immutable-root check. Data mutation and mutable local values follow the imported value rule.
See imported values for data mutation and mutable local values.
Причина
An imported binding belongs to its defining module. Rejecting replacement prevents an importing module from changing what other readers observe through that name.
Resolved public type visibility
An exported declaration publishes its resolved type, whether that type is annotated or inferred. Expand transparent type aliases before checking visibility. Every reachable record, enum, or newtype identity must be exported by its defining module. Check nested type components and type arguments recursively, including collections, structural records, unions, and function types. The rule covers function parameters and results, let and const bindings, type aliases, enum payloads, record fields, newtype bases, and exported protocol method parameters and results. A private alias whose expansion contains accessible types is accepted. A reachable private nominal type is rejected with TPZ3014 in the resolve phase. The primary location is the offending exported type reference when annotated, or the exported declaration's name when inferred.
Причина
Exporters publish the same type whether an annotation or inference determines it. Checking resolved identities prevents annotation spelling from changing visibility. Transparent aliases introduce no new identity, so callers need the expanded type rather than the private alias name.
Record defaults respect module privacy
Причина
Field defaults are ordinary expression contexts.
An exported function may expose an exported user protocol bound
Ссылкаexport protocol Labelled { function label(value: Self) -> string }export function describe<T: Labelled>(value: T) -> string { Labelled.label(value) }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
A private protocol is not selected through import
Ссылкаimport contracts { Hidden }
Нет стандартного вывода.protocol Hidden { function label(value: Self) -> string }export let marker = 0
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
protocol-name-not-exported at
example.tpz:1:20
An exported protocol cannot expose a private nominal parameter type
Ссылкаrecord Hidden { n: int }export protocol Render { function render(value: Self, input: Hidden) -> string }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
example.tpz:2:62
An exported protocol signature may use an exported nominal type
Ссылкаexport record Input { n: int }export protocol Render { function render(value: Self, input: Input) -> string }
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Imported values
An imported value is an immutable binding. The importing module cannot change its data through that binding. let mut local = imported receives an independent data value under collection value semantics. Changing the local leaves the exported value unchanged. Imported host resource handles, such as File, retain shared resource state.
Imported data follows collection value semantics. Import assignment rejects replacement. Immutable assignment rejects writes through an immutable root.
Причина
Importing a data value follows the same value semantics as assigning it. A mutable local therefore cannot change the exporting module's value.
Rejected source forms
СсылкаReserved import spellings
A use item and a string or template module path are rejected with TPZ2008.
Причина
Dotted imports give source dependencies one spelling. A second keyword or string path would name the same module through another syntax.
Rejected export spellings
The forms export { name } and export import module are rejected with TPZ2009.
Причина
An export prefix keeps visibility at the declaration. Separate export lists or import exports would give publication another place and spelling.
Complete import and export examples
СсылкаSave the complete file set shown for an example, then use its displayed command.
Select exports and rename a local binding
Ссылкаimport helpers { double as twice, increment }let result: int = twice(20) + increment
Нет стандартного вывода.export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
Нет стандартного вывода.
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Save helpers.tpz beside main.tpz. The following run example uses the same selected import and prints its result.
Run a selected import with an alias
Ссылкаimport std.io { writeLine }import helpers { double as twice, increment }let result: int = twice(20) + incrementwriteLine("{result}")
41
export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
41
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
41
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Bind a namespace under its final path segment
Ссылкаimport helperslet result: int = helpers.double(21)
Нет стандартного вывода.export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
Нет стандартного вывода.
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Choose a namespace name
Ссылкаimport helpers as numberslet result: int = numbers.double(21)
Нет стандартного вывода.export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
Нет стандартного вывода.
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Export an immutable binding
Ссылкаimport counters { count }let value: int = count
Нет стандартного вывода.export let count: int = 0
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 0.
Нет стандартного вывода.
Нет вывода ошибок.
- Пройдено · expected 0; observed 0
- Пройдено · stdout matches the authored expectation
- Пройдено · stderr matches the authored expectation
Use an exported value in a record default
Ссылкаimport std.ioimport defaultsrecord Item {value: int = defaults.seed}let item = Item {}io.writeLine("{item.value}")
41
export let visible: int = 0export let seed: int = 41let mut state: int = 42type Secret = int
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
41
Export the nominal type used by an inferred public result
Ссылкаimport liblet value: lib.Hidden = lib.make()let observed: int = value.value
Нет стандартного вывода.export record Hidden { value: int }export function make() { Hidden { value: 7 } }
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Export the nominal type used by a public binding
Ссылкаimport liblet value: lib.Hidden = lib.valuelet observed: int = value.value
Нет стандартного вывода.export record Hidden { value: int }export let value = Hidden { value: 7 }
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
A private alias of a public type is transparent
Ссылкаimport liblet value: int = lib.count()
Нет стандартного вывода.type Count = intexport function count() -> Count { 1 }
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Free calls, assignments, and loops in an entry
Ссылкаimport std.ioexport let value: int = 1let mut count: int = 0io.writeLine("free")for item in ([1]) {count = count + itemio.writeLine("loop")}io.writeLine("{count}")
free
loop
1
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
freeloop1
The same source file imported
Ссылкаimport helpersimport std.ioio.writeLine("{helpers.value}")
free
loop
1
1
import std.ioexport let value: int = 1let mut count: int = 0io.writeLine("free")for item in ([1]) {count = count + itemio.writeLine("loop")}io.writeLine("{count}")
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
freeloop11
A diamond initializes once in ready-identity order
Ссылкаimport aimport bimport std.ioio.writeLine("entry")
shared
b
z
a
entry
import zimport std.ioexport let value: int = {io.writeLine("a")z.value}
import sharedimport std.ioexport let value: int = {io.writeLine("b")shared.value}
import sharedimport std.ioexport let value: int = {io.writeLine("z")shared.value}
import std.ioexport let value: int = {io.writeLine("shared")1}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
sharedbzaentry
Reversing import lines preserves the initialization trace
Ссылкаimport std.ioimport bimport aio.writeLine("entry")
shared
b
z
a
entry
import zimport std.ioexport let value: int = {io.writeLine("a")z.value}
import sharedimport std.ioexport let value: int = {io.writeLine("b")shared.value}
import sharedimport std.ioexport let value: int = {io.writeLine("z")shared.value}
import std.ioexport let value: int = {io.writeLine("shared")1}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
sharedbzaentry
A namespace import initializes an export-less module
Ссылкаimport setupimport std.ioio.writeLine("entry")
setup
entry
import std.iolet initialized: int = {io.writeLine("setup")1}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
setupentry
Removing the back edge gives dependency-first effects
Ссылкаimport firstimport std.ioio.writeLine("entry")
second
first
entry
import secondimport std.ioexport let one: int = {io.writeLine("first")1}
import std.ioexport let two: int = {io.writeLine("second")2}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
secondfirstentry
Move the dependency before the initializer
Ссылкаlet second = 1export let first = second
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
The same source-order repair in an imported file
Ссылкаimport lib
Нет стандартного вывода.let second = 1export let first = second
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Repairing the fault completes the remaining initialization
Ссылкаimport aimport bimport cimport std.ioio.writeLine("entry")
a
b-before
b-after
c
entry
import std.ioexport let value: int = {io.writeLine("a")1}
import std.iofunction readAt(index: int) -> int {let values = [10]values[index]}export let value: int = {io.writeLine("b-before")readAt(0)}export let after: int = {io.writeLine("b-after")1}
import std.ioexport let value: int = {io.writeLine("c")1}
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
ab-beforeb-aftercentry
Omit the namespace alias to keep its default name
Ссылкаimport liblet result: int = lib.value
Нет стандартного вывода.export let value: int = 1
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Omit the selected alias to keep its source name
Ссылкаimport lib { value }let result: int = value
Нет стандартного вывода.export let value: int = 1
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Export every record binding after one initializer
Ссылкаimport libimport std.io { writeLine }writeLine("{lib.first}")writeLine("{lib.second}")
init
10
20
import std.io { writeLine }function make() -> { first: int, second: int } {writeLine("init"){ first: 10, second: 20 }}export let { first: first, second: second } = make()
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
init1020
An outer pattern annotation supplies each public binding type
Ссылкаimport lib { count, label }let number: int = countlet text: string = label
Нет стандартного вывода.export let { nested: { count: count }, label: label }: { nested: { count: int }, label: string } = { nested: { count: 4 }, label: "four" }
Ожидаемый результат
Ожидаемый результат
Проверка принимает программу. Код завершения 0.
Export names from an ordinary nominal record pattern
Ссылкаimport libimport std.io { writeLine }writeLine("{lib.first + lib.second}")
42
record Pair { first: int, second: int }export let Pair { first: first, second: second } = Pair { first: 20, second: 22 }
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
42
A mutable local leaves the exported array unchanged
Ссылкаimport std.ioimport helpers { items }let mut local = itemslocal.push(3)io.writeLine("{items.length}:{local.length}")
2:3
export let items = [1, 2]
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
2:3
Rejected forms and boundaries
СсылкаThe following files demonstrate rejected imports and exports. Compare their commands with the accepted examples above.
Use is not an import item
Ссылкаuse helpers
Нет стандартного вывода.error[TPZ2008]: `use` is reserved and unused; did you mean `import`?
--> main.tpz:1:1
|
1 | use helpers
| ^^^
main.tpz: 1 diagnostic
export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
reserved-use-item at
main.tpz:1:1
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ2008]: `use` is reserved and unused; did you mean `import`?--> main.tpz:1:1|1 | use helpers| ^^^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ2008; cause reserved-use-item; primary location asserted; additional diagnostics allow
A string is not a module path
Ссылкаimport "helpers"
Нет стандартного вывода.error[TPZ2008]: string and template module paths are reserved and unused; module paths are dotted identifiers
--> main.tpz:1:1
|
1 | import "helpers"
| ^^^^^^
main.tpz: 1 diagnostic
export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
reserved-string-module-path at
main.tpz:1:1
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ2008]: string and template module paths are reserved and unused; module paths are dotted identifiers--> main.tpz:1:1|1 | import "helpers"| ^^^^^^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ2008; cause reserved-string-module-path; primary location asserted; additional diagnostics allow
Export lists are rejected
Ссылкаfunction double(value: int) -> int {value + value}export { double }
Нет стандартного вывода.error[TPZ2009]: export lists are invalid syntax; put `export` on each public declaration
--> main.tpz:4:1
|
4 | export { double }
| ^^^^^^
main.tpz: 1 diagnostic
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
rejected-export-list at
main.tpz:4:1
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ2009]: export lists are invalid syntax; put `export` on each public declaration--> main.tpz:4:1|4 | export { double }| ^^^^^^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ2009; cause rejected-export-list; primary location asserted; additional diagnostics allow
Export import is rejected
Ссылкаexport import helpers
Нет стандартного вывода.error[TPZ2009]: re-export syntax does not exist (`export import ...` is rejected)
--> main.tpz:1:1
|
1 | export import helpers
| ^^^^^^
main.tpz: 1 diagnostic
export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
rejected-reexport at
main.tpz:1:1
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ2009]: re-export syntax does not exist (`export import ...` is rejected)--> main.tpz:1:1|1 | export import helpers| ^^^^^^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ2009; cause rejected-reexport; primary location asserted; additional diagnostics allow
A namespace alias and selection do not compose
Ссылкаimport helpers as names { double }
Нет стандартного вывода.error[TPZ2009]: a namespace alias and a selection list do not compose (`import m as ns { x }` is invalid syntax)
--> main.tpz:1:25
|
1 | import helpers as names { double }
| ^
main.tpz: 1 diagnostic
export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
namespace-alias-with-selection at
main.tpz:1:25
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ2009]: a namespace alias and a selection list do not compose (`import m as ns { x }` is invalid syntax)--> main.tpz:1:25|1 | import helpers as names { double }| ^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ2009; cause namespace-alias-with-selection; primary location asserted; additional diagnostics allow
Imports precede other items
Ссылкаlet before: int = 0import helpers
Нет стандартного вывода.error[TPZ2010]: imports form a prologue: every `import` precedes all other top-level items
--> main.tpz:2:1
|
2 | import helpers
| ^^^^^^^^^^^^^^
main.tpz: 1 diagnostic
export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
import-after-prologue at
main.tpz:2:1
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ2010]: imports form a prologue: every `import` precedes all other top-level items--> main.tpz:2:1|2 | import helpers| ^^^^^^^^^^^^^^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ2010; cause import-after-prologue; primary location asserted; additional diagnostics allow
A selected name must be exported
Ссылкаimport helpers { secret }
Нет стандартного вывода.error[TPZ3009]: `secret` is not exported by `helpers`
--> main.tpz:1:18
|
1 | import helpers { secret }
| ^^^^^^
main.tpz: 1 diagnostic
export function double(value: int) -> int {value + value}export let increment: int = 1let secret: int = 99
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
selected-name-not-exported at
main.tpz:1:18
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ3009]: `secret` is not exported by `helpers`--> main.tpz:1:18|1 | import helpers { secret }| ^^^^^^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ3009; cause selected-name-not-exported; primary location asserted; additional diagnostics allow
The target exports double and increment. The intended rejection concerns the private secret binding, not an empty export table.
Exporting a mutable let is rejected
Ссылкаexport let mut count: int = 0
Нет стандартного вывода.error[TPZ3011]: `export let mut` is a static error: exported bindings are immutable views
--> main.tpz:1:16
|
1 | export let mut count: int = 0
| ^^^^^
main.tpz: 1 diagnostic
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
mutable-let-export at
main.tpz:1:16
Наблюдаемые утверждения · Пройдено · 5.21.3
Код завершения 1.
Нет стандартного вывода.
error[TPZ3011]: `export let mut` is a static error: exported bindings are immutable views--> main.tpz:1:16|1 | export let mut count: int = 0| ^^^^^main.tpz: 1 diagnostic
- Пройдено · expected nonzero; observed 1
- Пройдено · stdout matches the authored expectation
- Пройдено · checking TPZ3011; cause mutable-let-export; primary location asserted; additional diagnostics allow
A record default cannot read a private mutable value
Ссылкаimport defaultsrecord Item {value: int = defaults.state}let item = Item {}
Нет стандартного вывода.export let visible: int = 0let seed: int = 41let mut state: int = 42type Secret = int
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
record-default-private-mutable-member at
main.tpz:3:27
A default value does not grant access to a private type
Ссылкаimport defaultsrecord Item {value: int = {let saved: defaults.Secret = 1saved}}let item = Item {}
Нет стандартного вывода.export let visible: int = 0let seed: int = 41let mut state: int = 42type Secret = int
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
record-default-private-type-member at
main.tpz:4:29
The private value remains inaccessible outside a default
Ссылкаimport defaultslet value: int = defaults.seed
Нет стандартного вывода.export let visible: int = 0let seed: int = 41let mut state: int = 42type Secret = int
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
namespace-private-let-outside-default at
main.tpz:2:27
Reject a private value in a record default
Ссылкаimport std.ioimport defaultsrecord Item {value: int = defaults.seed}let item = Item {}io.writeLine("{item.value}")
Нет стандартного вывода.export let visible: int = 0let seed: int = 41let mut state: int = 42type Secret = int
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
record-default-private-immutable-member at
main.tpz:4:27
An explicit public result cannot expose a private nominal type
Ссылкаimport liblet value = lib.make()
Нет стандартного вывода.record Hidden { value: int }export function make() -> Hidden { Hidden { value: 7 } }
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
lib.tpz:2:27
An inferred public result obeys the same visibility rule
Ссылкаimport liblet value = lib.make()
Нет стандартного вывода.record Hidden { value: int }export function make() { Hidden { value: 7 } }
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
lib.tpz:2:17
A collection result cannot hide a private element type
Ссылкаimport liblet value = lib.make()
Нет стандартного вывода.record Hidden { value: int }export function make() { [Hidden { value: 7 }] }
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
lib.tpz:2:17
An annotated exported binding cannot expose a private nominal type
Ссылкаimport liblet value = lib.value
Нет стандартного вывода.record Hidden { value: int }export let value: Hidden = Hidden { value: 7 }
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
lib.tpz:2:19
An inferred exported binding cannot expose a private nominal type
Ссылкаimport liblet value = lib.value
Нет стандартного вывода.record Hidden { value: int }export let value = Hidden { value: 7 }
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
lib.tpz:2:12
An alias expansion cannot hide a private nominal result
Ссылкаimport liblet value = lib.make()
Нет стандартного вывода.record Hidden { value: int }type Alias = Hiddenexport function make() -> Alias { Hidden { value: 7 } }
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
lib.tpz:3:27
An empty namespace still has no selectable member
Ссылкаimport setup { missing }
Нет стандартного вывода.let value: int = 1
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
selected-name-not-exported at
main.tpz:1:16
An import cycle is rejected before initialization
Ссылкаimport firstimport std.ioio.writeLine("entry")
Нет стандартного вывода.import secondimport std.ioexport let one: int = {io.writeLine("first")1}
import firstimport std.ioexport let two: int = {io.writeLine("second")2}
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
module-import-cycle at
first.tpz:1:8
An entry initializer cannot read a later binding
Ссылкаexport let first = secondlet second = 1
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
module-initializer-not-ready at
main.tpz:1:20
The same early read is rejected in an imported file
Ссылкаimport lib
Нет стандартного вывода.export let first = secondlet second = 1
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
module-initializer-not-ready at
lib.tpz:1:20
A fault preserves earlier output and stops remaining initialization
Ссылкаimport aimport bimport cimport std.ioio.writeLine("entry")
a
b-before
import std.ioexport let value: int = {io.writeLine("a")1}
import std.iofunction readAt(index: int) -> int {let values = [10]values[index]}export let value: int = {io.writeLine("b-before")readAt(1)}export let after: int = {io.writeLine("b-after")1}
import std.ioexport let value: int = {io.writeLine("c")1}
Ожидаемый результат
Ожидаемый результат
Этап отклонения run. Ненулевой код завершения.
diagnostic-tpz4001 at
b.tpz:4:5
ab-before
Reject a namespace alias repeating its default name
Ссылкаimport lib as liblet result: int = lib.value
Нет стандартного вывода.export let value: int = 1
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
redundant-import-alias at
main.tpz:1:15
This rejection is the intended TPZ2009/parse contract for a redundant alias. The reviewed SELF parser currently accepts the form. The limitation permits only the expected exit and diagnostic assertions to fail; the expected source location is the alias identifier.
Reject a selected alias repeating its source name
Ссылкаimport lib { value as value }let result: int = value
Нет стандартного вывода.export let value: int = 1
Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
redundant-import-alias at
main.tpz:1:23
This rejection is the intended TPZ2009/parse contract for a redundant alias. The reviewed SELF parser currently accepts the form. The limitation permits only the expected exit and diagnostic assertions to fail; the expected source location is the alias identifier.
Use plain let when a pattern publishes no binding
Ссылкаexport let _ = 1
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения parse. Ненулевой код завершения.
export-let-no-binding at
main.tpz:1:12
Export preserves the ordinary refutable-let rejection
Ссылкаlet maybe: Option<int> = None()export let Some(value) = maybe
Нет стандартного вывода.Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
diagnostics-refutable-let-pattern at
main.tpz:2:12
Each bound name must have a public resolved type
Ссылкаimport liblet observed = lib.count
Нет стандартного вывода.record Hidden { value: int }export let { item: item, count: count } = { item: Hidden { value: 1 }, count: 2 }
Ожидаемый результат
Ожидаемый результат
Этап отклонения resolve. Ненулевой код завершения.
modules-public-private-nominal at
lib.tpz:2:20
An imported array has an immutable root
Ссылкаimport helpers { items }items[0] = 9
Нет стандартного вывода.export let items = [1, 2]
Ожидаемый результат
Ожидаемый результат
Этап отклонения check. Ненулевой код завершения.
bindings-assignment-to-immutable at
main.tpz:2:1
Pending contracts
СсылкаRelated contracts
СсылкаFunctions and generics owns callable declarations, calls, and exported protocol-bound restrictions. The check command owns invocation, selected entry and root, output channels, and exit status. Module visibility does not redefine those contracts.
Import after non-import item →
Rejected module-adjacent form →
Invalid exported let pattern →
Assignment to imported binding →
Private type in exported surface →